further cleanups to the Binder code
This commit is contained in:
parent
f4687ac048
commit
86906013c2
|
@ -58,10 +58,7 @@ public abstract class ObjectNameNormalizer {
|
||||||
*/
|
*/
|
||||||
public String normalizeIdentifierQuotingAsString(String identifierText) {
|
public String normalizeIdentifierQuotingAsString(String identifierText) {
|
||||||
final Identifier identifier = normalizeIdentifierQuoting( identifierText );
|
final Identifier identifier = normalizeIdentifierQuoting( identifierText );
|
||||||
if ( identifier == null ) {
|
return identifier == null ? null : identifier.render( database().getDialect() );
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return identifier.render( database().getDialect() );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toDatabaseIdentifierText(String identifierText) {
|
public String toDatabaseIdentifierText(String identifierText) {
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.jboss.logging.Logger;
|
||||||
import static org.hibernate.cfg.BinderHelper.getOverridableAnnotation;
|
import static org.hibernate.cfg.BinderHelper.getOverridableAnnotation;
|
||||||
import static org.hibernate.cfg.BinderHelper.getPath;
|
import static org.hibernate.cfg.BinderHelper.getPath;
|
||||||
import static org.hibernate.cfg.BinderHelper.getRelativePath;
|
import static org.hibernate.cfg.BinderHelper.getRelativePath;
|
||||||
|
import static org.hibernate.internal.util.StringHelper.isEmpty;
|
||||||
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -310,7 +311,7 @@ public class AnnotatedColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isNameDeferred() {
|
public boolean isNameDeferred() {
|
||||||
return mappingColumn == null || StringHelper.isEmpty( mappingColumn.getName() );
|
return mappingColumn == null || isEmpty( mappingColumn.getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void redefineColumnName(String columnName, String propertyName, boolean applyNamingStrategy) {
|
public void redefineColumnName(String columnName, String propertyName, boolean applyNamingStrategy) {
|
||||||
|
@ -655,7 +656,7 @@ public class AnnotatedColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AnnotatedColumn[] buildColumnsOrFormulaFromAnnotation(
|
public static AnnotatedColumn[] buildColumnsOrFormulaFromAnnotation(
|
||||||
jakarta.persistence.Column[] columnAnns,
|
jakarta.persistence.Column[] columns,
|
||||||
org.hibernate.annotations.Formula formulaAnn,
|
org.hibernate.annotations.Formula formulaAnn,
|
||||||
Comment comment,
|
Comment comment,
|
||||||
Nullability nullability,
|
Nullability nullability,
|
||||||
|
@ -675,7 +676,7 @@ public class AnnotatedColumn {
|
||||||
return new AnnotatedColumn[] { formulaColumn };
|
return new AnnotatedColumn[] { formulaColumn };
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
jakarta.persistence.Column[] actualCols = overrideColumns( columnAnns, propertyHolder, inferredData);
|
jakarta.persistence.Column[] actualCols = overrideColumns( columns, propertyHolder, inferredData);
|
||||||
if ( actualCols == null ) {
|
if ( actualCols == null ) {
|
||||||
return buildImplicitColumn(
|
return buildImplicitColumn(
|
||||||
inferredData,
|
inferredData,
|
||||||
|
@ -702,7 +703,7 @@ public class AnnotatedColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static jakarta.persistence.Column[] overrideColumns(
|
private static jakarta.persistence.Column[] overrideColumns(
|
||||||
jakarta.persistence.Column[] columnAnns,
|
jakarta.persistence.Column[] columns,
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
PropertyData inferredData ) {
|
PropertyData inferredData ) {
|
||||||
final jakarta.persistence.Column[] overriddenCols = propertyHolder.getOverriddenColumn(
|
final jakarta.persistence.Column[] overriddenCols = propertyHolder.getOverriddenColumn(
|
||||||
|
@ -710,11 +711,11 @@ public class AnnotatedColumn {
|
||||||
);
|
);
|
||||||
if ( overriddenCols != null ) {
|
if ( overriddenCols != null ) {
|
||||||
//check for overridden first
|
//check for overridden first
|
||||||
if ( columnAnns != null && overriddenCols.length != columnAnns.length ) {
|
if ( columns != null && overriddenCols.length != columns.length ) {
|
||||||
//TODO: unfortunately, we never actually see this nice error message, since
|
//TODO: unfortunately, we never actually see this nice error message, since
|
||||||
// PersistentClass.validate() gets called first and produces a worse message
|
// PersistentClass.validate() gets called first and produces a worse message
|
||||||
throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
|
throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
|
||||||
+ "' specifies " + columnAnns.length
|
+ "' specifies " + columns.length
|
||||||
+ " '@AttributeOverride's but the overridden property has " + overriddenCols.length
|
+ " '@AttributeOverride's but the overridden property has " + overriddenCols.length
|
||||||
+ " columns (every column must have exactly one '@AttributeOverride')" );
|
+ " columns (every column must have exactly one '@AttributeOverride')" );
|
||||||
}
|
}
|
||||||
|
@ -722,7 +723,7 @@ public class AnnotatedColumn {
|
||||||
return overriddenCols.length == 0 ? null : overriddenCols;
|
return overriddenCols.length == 0 ? null : overriddenCols;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return columnAnns;
|
return columns;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -741,7 +742,7 @@ public class AnnotatedColumn {
|
||||||
final Database database = context.getMetadataCollector().getDatabase();
|
final Database database = context.getMetadataCollector().getDatabase();
|
||||||
final String sqlType = column.columnDefinition().isEmpty() ? null
|
final String sqlType = column.columnDefinition().isEmpty() ? null
|
||||||
: context.getObjectNameNormalizer().applyGlobalQuoting( column.columnDefinition() );
|
: context.getObjectNameNormalizer().applyGlobalQuoting( column.columnDefinition() );
|
||||||
final String tableName = StringHelper.isEmpty( column.table() ) ? ""
|
final String tableName = isEmpty( column.table() ) ? ""
|
||||||
: database.getJdbcEnvironment().getIdentifierHelper().toIdentifier( column.table() ).render();
|
: database.getJdbcEnvironment().getIdentifierHelper().toIdentifier( column.table() ).render();
|
||||||
// final Identifier logicalName = database.getJdbcEnvironment()
|
// final Identifier logicalName = database.getJdbcEnvironment()
|
||||||
// .getIdentifierHelper()
|
// .getIdentifierHelper()
|
||||||
|
@ -813,7 +814,7 @@ public class AnnotatedColumn {
|
||||||
final String columnName = column.name() != null && column.name().isEmpty() ? null
|
final String columnName = column.name() != null && column.name().isEmpty() ? null
|
||||||
: database.getJdbcEnvironment().getIdentifierHelper().toIdentifier( column.name() ).render();
|
: database.getJdbcEnvironment().getIdentifierHelper().toIdentifier( column.name() ).render();
|
||||||
// NOTE : this is the logical column name, not the physical!
|
// NOTE : this is the logical column name, not the physical!
|
||||||
return StringHelper.isEmpty( columnName ) && !StringHelper.isEmpty(suffixForDefaultColumnName)
|
return isEmpty( columnName ) && isNotEmpty( suffixForDefaultColumnName )
|
||||||
? inferredData.getPropertyName() + suffixForDefaultColumnName
|
? inferredData.getPropertyName() + suffixForDefaultColumnName
|
||||||
: columnName;
|
: columnName;
|
||||||
}
|
}
|
||||||
|
@ -823,16 +824,14 @@ public class AnnotatedColumn {
|
||||||
if ( xProperty != null ) {
|
if ( xProperty != null ) {
|
||||||
ColumnDefault columnDefault = getOverridableAnnotation( xProperty, ColumnDefault.class, context );
|
ColumnDefault columnDefault = getOverridableAnnotation( xProperty, ColumnDefault.class, context );
|
||||||
if ( columnDefault != null ) {
|
if ( columnDefault != null ) {
|
||||||
if (length!=1) {
|
if ( length!=1 ) {
|
||||||
throw new MappingException("@ColumnDefault may only be applied to single-column mappings");
|
throw new MappingException("@ColumnDefault may only be applied to single-column mappings");
|
||||||
}
|
}
|
||||||
setDefaultValue( columnDefault.value() );
|
setDefaultValue( columnDefault.value() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG.trace(
|
LOG.trace("Could not perform @ColumnDefault lookup as 'PropertyData' did not give access to XProperty");
|
||||||
"Could not perform @ColumnDefault lookup as 'PropertyData' did not give access to XProperty"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,9 +847,7 @@ public class AnnotatedColumn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG.trace(
|
LOG.trace("Could not perform @GeneratedColumn lookup as 'PropertyData' did not give access to XProperty");
|
||||||
"Could not perform @GeneratedColumn lookup as 'PropertyData' did not give access to XProperty"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -866,9 +863,7 @@ public class AnnotatedColumn {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG.trace(
|
LOG.trace("Could not perform @Check lookup as 'PropertyData' did not give access to XProperty");
|
||||||
"Could not perform @Check lookup as 'PropertyData' did not give access to XProperty"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,7 +888,7 @@ public class AnnotatedColumn {
|
||||||
|
|
||||||
private void processColumnTransformerExpressions(ColumnTransformer annotation) {
|
private void processColumnTransformerExpressions(ColumnTransformer annotation) {
|
||||||
if ( annotation != null ) {
|
if ( annotation != null ) {
|
||||||
if ( StringHelper.isEmpty( annotation.forColumn() )
|
if ( isEmpty( annotation.forColumn() )
|
||||||
// "" is the default value for annotations
|
// "" is the default value for annotations
|
||||||
|| annotation.forColumn().equals( logicalColumnName != null ? logicalColumnName : "" ) ) {
|
|| annotation.forColumn().equals( logicalColumnName != null ? logicalColumnName : "" ) ) {
|
||||||
readExpression = StringHelper.nullIfEmpty( annotation.read() );
|
readExpression = StringHelper.nullIfEmpty( annotation.read() );
|
||||||
|
@ -947,7 +942,7 @@ public class AnnotatedColumn {
|
||||||
column.setJoins(secondaryTables);
|
column.setJoins(secondaryTables);
|
||||||
column.setBuildingContext(context);
|
column.setBuildingContext(context);
|
||||||
// property name + suffix is an "explicit" column name
|
// property name + suffix is an "explicit" column name
|
||||||
boolean implicit = StringHelper.isEmpty( suffixForDefaultColumnName );
|
boolean implicit = isEmpty( suffixForDefaultColumnName );
|
||||||
if ( !implicit ) {
|
if ( !implicit ) {
|
||||||
column.setLogicalColumnName( propertyName + suffixForDefaultColumnName );
|
column.setLogicalColumnName( propertyName + suffixForDefaultColumnName );
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,10 @@ import org.hibernate.mapping.Value;
|
||||||
import static org.hibernate.cfg.BinderHelper.findColumnOwner;
|
import static org.hibernate.cfg.BinderHelper.findColumnOwner;
|
||||||
import static org.hibernate.cfg.BinderHelper.getRelativePath;
|
import static org.hibernate.cfg.BinderHelper.getRelativePath;
|
||||||
import static org.hibernate.cfg.BinderHelper.isEmptyAnnotationValue;
|
import static org.hibernate.cfg.BinderHelper.isEmptyAnnotationValue;
|
||||||
|
import static org.hibernate.cfg.BinderHelper.isEmptyOrNullAnnotationValue;
|
||||||
|
import static org.hibernate.internal.util.StringHelper.isEmpty;
|
||||||
|
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
||||||
|
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link jakarta.persistence.JoinColumn} annotation
|
* A {@link jakarta.persistence.JoinColumn} annotation
|
||||||
|
@ -90,46 +94,13 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
this.mappedBy = mappedBy;
|
this.mappedBy = mappedBy;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Due to @AnnotationOverride overriding rules, I don't want the constructor to be public
|
public boolean hasMappedBy() {
|
||||||
private AnnotatedJoinColumn() {
|
return isNotEmpty( mappedBy );
|
||||||
setMappedBy("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Due to @AnnotationOverride overriding rules, I don't want the constructor to be public
|
//Due to @AnnotationOverride overriding rules, I don't want the constructor to be public
|
||||||
//TODO get rid of it and use setters
|
private AnnotatedJoinColumn() {
|
||||||
private AnnotatedJoinColumn(
|
setMappedBy("");
|
||||||
String sqlType,
|
|
||||||
String name,
|
|
||||||
String comment,
|
|
||||||
boolean nullable,
|
|
||||||
boolean unique,
|
|
||||||
boolean insertable,
|
|
||||||
boolean updatable,
|
|
||||||
String referencedColumn,
|
|
||||||
String secondaryTable,
|
|
||||||
Map<String, Join> joins,
|
|
||||||
PropertyHolder propertyHolder,
|
|
||||||
String propertyName,
|
|
||||||
String mappedBy,
|
|
||||||
boolean isImplicit,
|
|
||||||
MetadataBuildingContext buildingContext) {
|
|
||||||
super();
|
|
||||||
setImplicit( isImplicit );
|
|
||||||
setSqlType( sqlType );
|
|
||||||
setLogicalColumnName( name );
|
|
||||||
setComment( comment );
|
|
||||||
setNullable( nullable );
|
|
||||||
setUnique( unique );
|
|
||||||
setInsertable( insertable );
|
|
||||||
setUpdatable( updatable );
|
|
||||||
setExplicitTableName( secondaryTable );
|
|
||||||
setPropertyHolder( propertyHolder );
|
|
||||||
setJoins( joins );
|
|
||||||
setBuildingContext( buildingContext );
|
|
||||||
setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
|
||||||
bind();
|
|
||||||
this.referencedColumn = referencedColumn;
|
|
||||||
this.mappedBy = mappedBy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getReferencedColumn() {
|
public String getReferencedColumn() {
|
||||||
|
@ -137,44 +108,55 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AnnotatedJoinColumn[] buildJoinColumnsOrFormulas(
|
public static AnnotatedJoinColumn[] buildJoinColumnsOrFormulas(
|
||||||
JoinColumnOrFormula[] anns,
|
JoinColumnOrFormula[] joinColumnOrFormulas,
|
||||||
String mappedBy,
|
String mappedBy,
|
||||||
Map<String, Join> joins,
|
Map<String, Join> joins,
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
String propertyName,
|
String propertyName,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
AnnotatedJoinColumn[] joinColumns = new AnnotatedJoinColumn[anns.length];
|
final AnnotatedJoinColumn[] joinColumns = new AnnotatedJoinColumn[joinColumnOrFormulas.length];
|
||||||
for (int i = 0; i < anns.length; i++) {
|
for (int i = 0; i < joinColumnOrFormulas.length; i++) {
|
||||||
JoinColumnOrFormula join = anns[i];
|
JoinColumnOrFormula columnOrFormula = joinColumnOrFormulas[i];
|
||||||
JoinFormula formula = join.formula();
|
JoinFormula formula = columnOrFormula.formula();
|
||||||
if ( formula.value() != null && !formula.value().isEmpty() ) {
|
if ( formula.value() != null && !formula.value().isEmpty() ) {
|
||||||
joinColumns[i] = buildJoinFormula(
|
joinColumns[i] = buildJoinFormula( formula, joins, propertyHolder, propertyName, buildingContext );
|
||||||
formula, mappedBy, joins, propertyHolder, propertyName, buildingContext
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
joinColumns[i] = buildJoinColumns(
|
joinColumns[i] = buildJoinColumn( mappedBy, joins, propertyHolder, propertyName, buildingContext, columnOrFormula );
|
||||||
new JoinColumn[] { join.column() }, null, mappedBy, joins, propertyHolder, propertyName, buildingContext
|
|
||||||
)[0];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return joinColumns;
|
return joinColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static AnnotatedJoinColumn buildJoinColumn(
|
||||||
|
String mappedBy,
|
||||||
|
Map<String, Join> joins,
|
||||||
|
PropertyHolder propertyHolder,
|
||||||
|
String propertyName, MetadataBuildingContext buildingContext,
|
||||||
|
JoinColumnOrFormula join) {
|
||||||
|
return buildJoinColumns(
|
||||||
|
new JoinColumn[]{ join.column() },
|
||||||
|
null,
|
||||||
|
mappedBy,
|
||||||
|
joins,
|
||||||
|
propertyHolder,
|
||||||
|
propertyName,
|
||||||
|
buildingContext
|
||||||
|
)[0];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* build join formula
|
* build join formula
|
||||||
*/
|
*/
|
||||||
public static AnnotatedJoinColumn buildJoinFormula(
|
public static AnnotatedJoinColumn buildJoinFormula(
|
||||||
JoinFormula ann,
|
JoinFormula joinFormula,
|
||||||
String mappedBy,
|
|
||||||
Map<String, Join> joins,
|
Map<String, Join> joins,
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
String propertyName,
|
String propertyName,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
AnnotatedJoinColumn formulaColumn = new AnnotatedJoinColumn();
|
AnnotatedJoinColumn formulaColumn = new AnnotatedJoinColumn();
|
||||||
formulaColumn.setFormula( ann.value() );
|
formulaColumn.setFormula( joinFormula.value() );
|
||||||
formulaColumn.setReferencedColumn(ann.referencedColumnName());
|
formulaColumn.setReferencedColumn(joinFormula.referencedColumnName());
|
||||||
formulaColumn.setBuildingContext( buildingContext );
|
formulaColumn.setBuildingContext( buildingContext );
|
||||||
formulaColumn.setPropertyHolder( propertyHolder );
|
formulaColumn.setPropertyHolder( propertyHolder );
|
||||||
formulaColumn.setJoins( joins );
|
formulaColumn.setJoins( joins );
|
||||||
|
@ -184,7 +166,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AnnotatedJoinColumn[] buildJoinColumns(
|
public static AnnotatedJoinColumn[] buildJoinColumns(
|
||||||
JoinColumn[] anns,
|
JoinColumn[] joinColumns,
|
||||||
Comment comment,
|
Comment comment,
|
||||||
String mappedBy,
|
String mappedBy,
|
||||||
Map<String, Join> joins,
|
Map<String, Join> joins,
|
||||||
|
@ -192,12 +174,19 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
String propertyName,
|
String propertyName,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
return buildJoinColumnsWithDefaultColumnSuffix(
|
return buildJoinColumnsWithDefaultColumnSuffix(
|
||||||
anns, comment, mappedBy, joins, propertyHolder, propertyName, "", buildingContext
|
joinColumns,
|
||||||
|
comment,
|
||||||
|
mappedBy,
|
||||||
|
joins,
|
||||||
|
propertyHolder,
|
||||||
|
propertyName,
|
||||||
|
"",
|
||||||
|
buildingContext
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AnnotatedJoinColumn[] buildJoinColumnsWithDefaultColumnSuffix(
|
public static AnnotatedJoinColumn[] buildJoinColumnsWithDefaultColumnSuffix(
|
||||||
JoinColumn[] anns,
|
JoinColumn[] joinColumns,
|
||||||
Comment comment,
|
Comment comment,
|
||||||
String mappedBy,
|
String mappedBy,
|
||||||
Map<String, Join> joins,
|
Map<String, Join> joins,
|
||||||
|
@ -205,10 +194,8 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
String propertyName,
|
String propertyName,
|
||||||
String suffixForDefaultColumnName,
|
String suffixForDefaultColumnName,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
JoinColumn[] actualColumns = propertyHolder.getOverriddenJoinColumn(
|
JoinColumn[] overriddes = propertyHolder.getOverriddenJoinColumn( qualify( propertyHolder.getPath(), propertyName ) );
|
||||||
StringHelper.qualify( propertyHolder.getPath(), propertyName )
|
JoinColumn[] actualColumns = overriddes == null ? joinColumns : overriddes;
|
||||||
);
|
|
||||||
if ( actualColumns == null ) actualColumns = anns;
|
|
||||||
if ( actualColumns == null || actualColumns.length == 0 ) {
|
if ( actualColumns == null || actualColumns.length == 0 ) {
|
||||||
return new AnnotatedJoinColumn[] {
|
return new AnnotatedJoinColumn[] {
|
||||||
buildJoinColumn(
|
buildJoinColumn(
|
||||||
|
@ -224,9 +211,8 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int size = actualColumns.length;
|
final AnnotatedJoinColumn[] result = new AnnotatedJoinColumn[actualColumns.length];
|
||||||
AnnotatedJoinColumn[] result = new AnnotatedJoinColumn[size];
|
for (int index = 0; index < actualColumns.length; index++ ) {
|
||||||
for (int index = 0; index < size; index++) {
|
|
||||||
result[index] = buildJoinColumn(
|
result[index] = buildJoinColumn(
|
||||||
actualColumns[index],
|
actualColumns[index],
|
||||||
comment,
|
comment,
|
||||||
|
@ -246,88 +232,84 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
* build join column for SecondaryTables
|
* build join column for SecondaryTables
|
||||||
*/
|
*/
|
||||||
private static AnnotatedJoinColumn buildJoinColumn(
|
private static AnnotatedJoinColumn buildJoinColumn(
|
||||||
JoinColumn ann,
|
JoinColumn joinColumn,
|
||||||
Comment comment,
|
Comment comment,
|
||||||
String mappedBy, Map<String, Join> joins,
|
String mappedBy, Map<String, Join> joins,
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
String propertyName,
|
String propertyName,
|
||||||
String suffixForDefaultColumnName,
|
String suffixForDefaultColumnName,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
if ( ann != null ) {
|
if ( joinColumn != null ) {
|
||||||
if ( !BinderHelper.isEmptyOrNullAnnotationValue( mappedBy ) ) {
|
if ( !isEmptyOrNullAnnotationValue( mappedBy ) ) {
|
||||||
throw new AnnotationException(
|
throw new AnnotationException(
|
||||||
"Association '" + getRelativePath( propertyHolder, propertyName )
|
"Association '" + getRelativePath( propertyHolder, propertyName )
|
||||||
+ "' is 'mappedBy' a different entity and may not explicitly specify the '@JoinColumn'"
|
+ "' is 'mappedBy' a different entity and may not explicitly specify the '@JoinColumn'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
AnnotatedJoinColumn joinColumn = new AnnotatedJoinColumn();
|
AnnotatedJoinColumn column = new AnnotatedJoinColumn();
|
||||||
joinColumn.setComment( comment != null ? comment.value() : null );
|
column.setComment( comment != null ? comment.value() : null );
|
||||||
joinColumn.setBuildingContext( buildingContext );
|
column.setBuildingContext( buildingContext );
|
||||||
joinColumn.setJoinAnnotation( ann, null );
|
column.setJoinAnnotation( joinColumn, null );
|
||||||
if ( StringHelper.isEmpty( joinColumn.getLogicalColumnName() )
|
if ( isEmpty( column.getLogicalColumnName() ) && isNotEmpty( suffixForDefaultColumnName ) ) {
|
||||||
&& ! StringHelper.isEmpty( suffixForDefaultColumnName ) ) {
|
column.setLogicalColumnName( propertyName + suffixForDefaultColumnName );
|
||||||
joinColumn.setLogicalColumnName( propertyName + suffixForDefaultColumnName );
|
|
||||||
}
|
}
|
||||||
joinColumn.setJoins( joins );
|
column.setJoins( joins );
|
||||||
joinColumn.setPropertyHolder( propertyHolder );
|
column.setPropertyHolder( propertyHolder );
|
||||||
joinColumn.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
||||||
joinColumn.setImplicit( false );
|
column.setImplicit( false );
|
||||||
joinColumn.bind();
|
column.bind();
|
||||||
return joinColumn;
|
return column;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AnnotatedJoinColumn joinColumn = new AnnotatedJoinColumn();
|
AnnotatedJoinColumn column = new AnnotatedJoinColumn();
|
||||||
joinColumn.setMappedBy( mappedBy );
|
column.setMappedBy( mappedBy );
|
||||||
joinColumn.setJoins( joins );
|
column.setJoins( joins );
|
||||||
joinColumn.setPropertyHolder( propertyHolder );
|
column.setPropertyHolder( propertyHolder );
|
||||||
joinColumn.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
||||||
// property name + suffix is an "explicit" column name
|
// property name + suffix is an "explicit" column name
|
||||||
if ( !StringHelper.isEmpty( suffixForDefaultColumnName ) ) {
|
if ( isNotEmpty( suffixForDefaultColumnName ) ) {
|
||||||
joinColumn.setLogicalColumnName( propertyName + suffixForDefaultColumnName );
|
column.setLogicalColumnName( propertyName + suffixForDefaultColumnName );
|
||||||
joinColumn.setImplicit( false );
|
column.setImplicit( false );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
joinColumn.setImplicit( true );
|
column.setImplicit( true );
|
||||||
}
|
}
|
||||||
joinColumn.setBuildingContext( buildingContext );
|
column.setBuildingContext( buildingContext );
|
||||||
joinColumn.bind();
|
column.bind();
|
||||||
return joinColumn;
|
return column;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO default name still useful in association table
|
// TODO default name still useful in association table
|
||||||
public void setJoinAnnotation(JoinColumn annJoin, String defaultName) {
|
public void setJoinAnnotation(JoinColumn joinColumn, String defaultName) {
|
||||||
if ( annJoin == null ) {
|
if ( joinColumn == null ) {
|
||||||
setImplicit( true );
|
setImplicit( true );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setImplicit( false );
|
setImplicit( false );
|
||||||
if ( !isEmptyAnnotationValue( annJoin.columnDefinition() ) ) {
|
if ( !isEmptyAnnotationValue( joinColumn.columnDefinition() ) ) {
|
||||||
setSqlType( getBuildingContext().getObjectNameNormalizer().applyGlobalQuoting( annJoin.columnDefinition() ) );
|
setSqlType( getBuildingContext().getObjectNameNormalizer().applyGlobalQuoting( joinColumn.columnDefinition() ) );
|
||||||
}
|
}
|
||||||
if ( !isEmptyAnnotationValue( annJoin.name() ) ) {
|
if ( !isEmptyAnnotationValue( joinColumn.name() ) ) {
|
||||||
setLogicalColumnName( annJoin.name() );
|
setLogicalColumnName( joinColumn.name() );
|
||||||
}
|
}
|
||||||
setNullable( annJoin.nullable() );
|
setNullable( joinColumn.nullable() );
|
||||||
setUnique( annJoin.unique() );
|
setUnique( joinColumn.unique() );
|
||||||
setInsertable( annJoin.insertable() );
|
setInsertable( joinColumn.insertable() );
|
||||||
setUpdatable( annJoin.updatable() );
|
setUpdatable( joinColumn.updatable() );
|
||||||
setReferencedColumn( annJoin.referencedColumnName() );
|
setReferencedColumn( joinColumn.referencedColumnName() );
|
||||||
|
|
||||||
if ( isEmptyAnnotationValue( annJoin.table() ) ) {
|
if ( isEmptyAnnotationValue( joinColumn.table() ) ) {
|
||||||
setExplicitTableName( "" );
|
setExplicitTableName( "" );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
final Identifier logicalIdentifier = getBuildingContext().getMetadataCollector()
|
final Database database = getBuildingContext().getMetadataCollector().getDatabase();
|
||||||
.getDatabase()
|
final Identifier logicalIdentifier = database.toIdentifier( joinColumn.table() );
|
||||||
.toIdentifier( annJoin.table() );
|
|
||||||
final Identifier physicalIdentifier = getBuildingContext().getBuildingOptions()
|
final Identifier physicalIdentifier = getBuildingContext().getBuildingOptions()
|
||||||
.getPhysicalNamingStrategy()
|
.getPhysicalNamingStrategy()
|
||||||
.toPhysicalTableName( logicalIdentifier, getBuildingContext().getMetadataCollector().getDatabase().getJdbcEnvironment() );
|
.toPhysicalTableName( logicalIdentifier, database.getJdbcEnvironment() );
|
||||||
setExplicitTableName(
|
setExplicitTableName( physicalIdentifier.render( database.getDialect() ) );
|
||||||
physicalIdentifier.render( getBuildingContext().getMetadataCollector().getDatabase().getDialect() )
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -336,73 +318,60 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
* Build JoinColumn for a JOINED hierarchy
|
* Build JoinColumn for a JOINED hierarchy
|
||||||
*/
|
*/
|
||||||
public static AnnotatedJoinColumn buildJoinColumn(
|
public static AnnotatedJoinColumn buildJoinColumn(
|
||||||
PrimaryKeyJoinColumn pkJoinAnn,
|
PrimaryKeyJoinColumn primaryKeyJoinColumn,
|
||||||
JoinColumn joinAnn,
|
JoinColumn joinColumn,
|
||||||
Value identifier,
|
Value identifier,
|
||||||
Map<String, Join> joins,
|
Map<String, Join> joins,
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
|
|
||||||
final String defaultName = context.getMetadataCollector().getLogicalColumnName(
|
final String defaultColumnName = context.getMetadataCollector().getLogicalColumnName(
|
||||||
identifier.getTable(),
|
identifier.getTable(),
|
||||||
identifier.getColumns().get(0).getQuotedName()
|
identifier.getColumns().get(0).getQuotedName()
|
||||||
);
|
);
|
||||||
final ObjectNameNormalizer normalizer = context.getObjectNameNormalizer();
|
final ObjectNameNormalizer normalizer = context.getObjectNameNormalizer();
|
||||||
|
|
||||||
if ( pkJoinAnn != null || joinAnn != null ) {
|
if ( primaryKeyJoinColumn != null || joinColumn != null ) {
|
||||||
String colName;
|
final String columnName;
|
||||||
String columnDefinition;
|
final String columnDefinition;
|
||||||
String referencedColumnName;
|
final String referencedColumnName;
|
||||||
if ( pkJoinAnn != null ) {
|
if ( primaryKeyJoinColumn != null ) {
|
||||||
colName = pkJoinAnn.name();
|
columnName = primaryKeyJoinColumn.name();
|
||||||
columnDefinition = pkJoinAnn.columnDefinition();
|
columnDefinition = primaryKeyJoinColumn.columnDefinition();
|
||||||
referencedColumnName = pkJoinAnn.referencedColumnName();
|
referencedColumnName = primaryKeyJoinColumn.referencedColumnName();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
colName = joinAnn.name();
|
columnName = joinColumn.name();
|
||||||
columnDefinition = joinAnn.columnDefinition();
|
columnDefinition = joinColumn.columnDefinition();
|
||||||
referencedColumnName = joinAnn.referencedColumnName();
|
referencedColumnName = joinColumn.referencedColumnName();
|
||||||
}
|
}
|
||||||
return new AnnotatedJoinColumn(
|
final String columnDef = columnDefinition.isEmpty() ? null
|
||||||
columnDefinition.isEmpty()
|
: normalizer.toDatabaseIdentifierText( columnDefinition );
|
||||||
? null
|
final String logicalColumnName = columnName != null && columnName.isEmpty()
|
||||||
: normalizer.toDatabaseIdentifierText( columnDefinition ),
|
? normalizer.normalizeIdentifierQuotingAsString( defaultColumnName )
|
||||||
colName != null && colName.isEmpty()
|
: normalizer.normalizeIdentifierQuotingAsString( columnName );
|
||||||
? normalizer.normalizeIdentifierQuotingAsString( defaultName )
|
AnnotatedJoinColumn column = new AnnotatedJoinColumn();
|
||||||
: normalizer.normalizeIdentifierQuotingAsString( colName ),
|
column.setSqlType( columnDef );
|
||||||
null,
|
column.setLogicalColumnName( logicalColumnName );
|
||||||
false,
|
column.setReferencedColumn( referencedColumnName );
|
||||||
false,
|
column.setPropertyHolder( propertyHolder );
|
||||||
true,
|
column.setJoins( joins );
|
||||||
true,
|
column.setBuildingContext( context );
|
||||||
referencedColumnName,
|
column.setImplicit( false );
|
||||||
null,
|
column.setNullable( false );
|
||||||
joins,
|
column.bind();
|
||||||
propertyHolder,
|
return column;
|
||||||
null,
|
|
||||||
null,
|
|
||||||
false,
|
|
||||||
context
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new AnnotatedJoinColumn(
|
AnnotatedJoinColumn column = new AnnotatedJoinColumn();
|
||||||
null,
|
column.setLogicalColumnName( normalizer.normalizeIdentifierQuotingAsString( defaultColumnName ) );
|
||||||
normalizer.normalizeIdentifierQuotingAsString( defaultName ),
|
column.setPropertyHolder( propertyHolder );
|
||||||
null,
|
column.setJoins( joins );
|
||||||
false,
|
column.setBuildingContext( context );
|
||||||
false,
|
column.setImplicit( true );
|
||||||
true,
|
column.setNullable( false );
|
||||||
true,
|
column.bind();
|
||||||
null,
|
return column;
|
||||||
null,
|
|
||||||
joins,
|
|
||||||
propertyHolder,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
true,
|
|
||||||
context
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -737,31 +706,25 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addColumnBinding(SimpleValue value) {
|
protected void addColumnBinding(SimpleValue value) {
|
||||||
if ( StringHelper.isEmpty( mappedBy ) ) {
|
if ( isEmpty( mappedBy ) ) {
|
||||||
// was the column explicitly quoted in the mapping/annotation
|
// was the column explicitly quoted in the mapping/annotation
|
||||||
// TODO: in metamodel, we need to better split global quoting and explicit quoting w/ respect to logical names
|
// TODO: in metamodel, we need to better split global quoting and explicit quoting w/ respect to logical names
|
||||||
boolean isLogicalColumnQuoted = StringHelper.isQuoted( getLogicalColumnName() );
|
boolean isLogicalColumnQuoted = StringHelper.isQuoted( getLogicalColumnName() );
|
||||||
|
|
||||||
final ObjectNameNormalizer nameNormalizer = getBuildingContext().getObjectNameNormalizer();
|
final ObjectNameNormalizer nameNormalizer = getBuildingContext().getObjectNameNormalizer();
|
||||||
final String logicalColumnName = nameNormalizer.normalizeIdentifierQuotingAsString( getLogicalColumnName() );
|
final String logicalColumnName = nameNormalizer.normalizeIdentifierQuotingAsString( getLogicalColumnName() );
|
||||||
final String referencedColumn = nameNormalizer.normalizeIdentifierQuotingAsString( getReferencedColumn() );
|
final String referencedColumn = nameNormalizer.normalizeIdentifierQuotingAsString( getReferencedColumn() );
|
||||||
final String unquotedLogColName = StringHelper.unquote( logicalColumnName );
|
final String unquotedLogColName = StringHelper.unquote( logicalColumnName );
|
||||||
final String unquotedRefColumn = StringHelper.unquote( referencedColumn );
|
final String unquotedRefColumn = StringHelper.unquote( referencedColumn );
|
||||||
|
final String collectionColName = isNotEmpty( unquotedLogColName )
|
||||||
String logicalCollectionColumnName = StringHelper.isNotEmpty( unquotedLogColName )
|
|
||||||
? unquotedLogColName
|
? unquotedLogColName
|
||||||
: getPropertyName() + '_' + unquotedRefColumn;
|
: getPropertyName() + '_' + unquotedRefColumn;
|
||||||
logicalCollectionColumnName = getBuildingContext().getMetadataCollector()
|
final InFlightMetadataCollector collector = getBuildingContext().getMetadataCollector();
|
||||||
.getDatabase()
|
final String logicalCollectionColumnName = collector.getDatabase()
|
||||||
.getJdbcEnvironment()
|
.getJdbcEnvironment()
|
||||||
.getIdentifierHelper()
|
.getIdentifierHelper()
|
||||||
.toIdentifier( logicalCollectionColumnName, isLogicalColumnQuoted )
|
.toIdentifier( collectionColName, isLogicalColumnQuoted )
|
||||||
.render();
|
.render();
|
||||||
getBuildingContext().getMetadataCollector().addColumnNameBinding(
|
collector.addColumnNameBinding( value.getTable(), logicalCollectionColumnName, getMappingColumn() );
|
||||||
value.getTable(),
|
|
||||||
logicalCollectionColumnName,
|
|
||||||
getMappingColumn()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -802,7 +765,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
boolean explicitColumnReference = false;
|
boolean explicitColumnReference = false;
|
||||||
for ( AnnotatedJoinColumn column : columns ) {
|
for ( AnnotatedJoinColumn column : columns ) {
|
||||||
final String logicalReferencedColumnName = column.getReferencedColumn();
|
final String logicalReferencedColumnName = column.getReferencedColumn();
|
||||||
if ( StringHelper.isNotEmpty( logicalReferencedColumnName ) ) {
|
if ( isNotEmpty( logicalReferencedColumnName ) ) {
|
||||||
explicitColumnReference = true;
|
explicitColumnReference = true;
|
||||||
if ( !keyColumns.contains( column( context, table, logicalReferencedColumnName ) ) ) {
|
if ( !keyColumns.contains( column( context, table, logicalReferencedColumnName ) ) ) {
|
||||||
// we have a column which does not belong to the PK
|
// we have a column which does not belong to the PK
|
||||||
|
@ -844,7 +807,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
if ( mappingColumn != null ) {
|
if ( mappingColumn != null ) {
|
||||||
// columnDefinition can also be specified using @JoinColumn, hence we have to check
|
// columnDefinition can also be specified using @JoinColumn, hence we have to check
|
||||||
// whether it is set or not
|
// whether it is set or not
|
||||||
if ( StringHelper.isEmpty( sqlType ) ) {
|
if ( isEmpty( sqlType ) ) {
|
||||||
sqlType = column.getSqlType();
|
sqlType = column.getSqlType();
|
||||||
mappingColumn.setSqlType( sqlType );
|
mappingColumn.setSqlType( sqlType );
|
||||||
}
|
}
|
||||||
|
@ -862,46 +825,44 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static AnnotatedJoinColumn[] buildJoinTableJoinColumns(
|
public static AnnotatedJoinColumn[] buildJoinTableJoinColumns(
|
||||||
JoinColumn[] annJoins,
|
JoinColumn[] joinColumns,
|
||||||
Map<String, Join> secondaryTables,
|
Map<String, Join> secondaryTables,
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
String propertyName,
|
String propertyName,
|
||||||
String mappedBy,
|
String mappedBy,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
AnnotatedJoinColumn[] joinColumns;
|
if ( joinColumns == null ) {
|
||||||
if ( annJoins == null ) {
|
final AnnotatedJoinColumn column = new AnnotatedJoinColumn();
|
||||||
AnnotatedJoinColumn currentJoinColumn = new AnnotatedJoinColumn();
|
column.setImplicit( true );
|
||||||
currentJoinColumn.setImplicit( true );
|
column.setNullable( false ); //I break the spec, but it's for good
|
||||||
currentJoinColumn.setNullable( false ); //I break the spec, but it's for good
|
column.setPropertyHolder( propertyHolder );
|
||||||
currentJoinColumn.setPropertyHolder( propertyHolder );
|
column.setJoins( secondaryTables );
|
||||||
currentJoinColumn.setJoins( secondaryTables );
|
column.setBuildingContext( buildingContext );
|
||||||
currentJoinColumn.setBuildingContext( buildingContext );
|
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
||||||
currentJoinColumn.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
column.setMappedBy( mappedBy );
|
||||||
currentJoinColumn.setMappedBy( mappedBy );
|
column.bind();
|
||||||
currentJoinColumn.bind();
|
return new AnnotatedJoinColumn[] { column };
|
||||||
joinColumns = new AnnotatedJoinColumn[] { currentJoinColumn };
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
joinColumns = new AnnotatedJoinColumn[annJoins.length];
|
final AnnotatedJoinColumn[] columns = new AnnotatedJoinColumn[joinColumns.length];
|
||||||
JoinColumn annJoin;
|
int length = joinColumns.length;
|
||||||
int length = annJoins.length;
|
|
||||||
for (int index = 0; index < length; index++) {
|
for (int index = 0; index < length; index++) {
|
||||||
annJoin = annJoins[index];
|
final JoinColumn joinColumn = joinColumns[index];
|
||||||
AnnotatedJoinColumn currentJoinColumn = new AnnotatedJoinColumn();
|
final AnnotatedJoinColumn column = new AnnotatedJoinColumn();
|
||||||
currentJoinColumn.setImplicit( true );
|
column.setImplicit( true );
|
||||||
currentJoinColumn.setPropertyHolder( propertyHolder );
|
column.setPropertyHolder( propertyHolder );
|
||||||
currentJoinColumn.setJoins( secondaryTables );
|
column.setJoins( secondaryTables );
|
||||||
currentJoinColumn.setBuildingContext( buildingContext );
|
column.setBuildingContext( buildingContext );
|
||||||
currentJoinColumn.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
||||||
currentJoinColumn.setMappedBy( mappedBy );
|
column.setMappedBy( mappedBy );
|
||||||
currentJoinColumn.setJoinAnnotation( annJoin, propertyName );
|
column.setJoinAnnotation( joinColumn, propertyName );
|
||||||
currentJoinColumn.setNullable( false ); //I break the spec, but it's for good
|
column.setNullable( false ); //I break the spec, but it's for good
|
||||||
//done after the annotation to override it
|
//done after the annotation to override it
|
||||||
currentJoinColumn.bind();
|
column.bind();
|
||||||
joinColumns[index] = currentJoinColumn;
|
columns[index] = column;
|
||||||
}
|
}
|
||||||
|
return columns;
|
||||||
}
|
}
|
||||||
return joinColumns;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMappedBy(String entityName, String jpaEntityName, String logicalTableName, String mappedByProperty) {
|
public void setMappedBy(String entityName, String jpaEntityName, String logicalTableName, String mappedByProperty) {
|
||||||
|
|
|
@ -178,26 +178,12 @@ import static org.hibernate.internal.util.StringHelper.nullIfEmpty;
|
||||||
import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY;
|
import static org.hibernate.mapping.SimpleValue.DEFAULT_ID_GEN_STRATEGY;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSR 175 annotation binder which reads the annotations from classes, applies the
|
* Reads annotations from Java classes and produces the Hibernate configuration-time metamodel,
|
||||||
* principles of the EJB3 spec and produces the Hibernate configuration-time metamodel
|
* that is, the objects defined in the package {@link org.hibernate.mapping}.
|
||||||
* (the classes in the {@link org.hibernate.mapping} package)
|
|
||||||
* <p/>
|
|
||||||
* Some design description
|
|
||||||
* I tried to remove any link to annotation except from the 2 first level of
|
|
||||||
* method call.
|
|
||||||
* It'll enable to:
|
|
||||||
* - facilitate annotation overriding
|
|
||||||
* - mutualize one day xml and annotation binder (probably a dream though)
|
|
||||||
* - split this huge class in smaller mapping oriented classes
|
|
||||||
*
|
|
||||||
* bindSomething usually create the mapping container and is accessed by one of the 2 first level method
|
|
||||||
* makeSomething usually create the mapping container and is accessed by bindSomething[else]
|
|
||||||
* fillSomething take the container into parameter and fill it.
|
|
||||||
*
|
*
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
* @author Hardy Ferentschik
|
* @author Hardy Ferentschik
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public final class AnnotationBinder {
|
public final class AnnotationBinder {
|
||||||
private static final CoreMessageLogger LOG = messageLogger( AnnotationBinder.class );
|
private static final CoreMessageLogger LOG = messageLogger( AnnotationBinder.class );
|
||||||
|
|
||||||
|
@ -1262,8 +1248,7 @@ public final class AnnotationBinder {
|
||||||
columnsBuilder,
|
columnsBuilder,
|
||||||
columns,
|
columns,
|
||||||
returnedClass,
|
returnedClass,
|
||||||
propertyBinder,
|
propertyBinder
|
||||||
isId
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1349,18 +1334,16 @@ public final class AnnotationBinder {
|
||||||
ColumnsBuilder columnsBuilder,
|
ColumnsBuilder columnsBuilder,
|
||||||
AnnotatedColumn[] columns,
|
AnnotatedColumn[] columns,
|
||||||
XClass returnedClass,
|
XClass returnedClass,
|
||||||
PropertyBinder propertyBinder,
|
PropertyBinder propertyBinder) {
|
||||||
boolean isId) {
|
|
||||||
//define whether the type is a component or not
|
|
||||||
|
|
||||||
boolean isComponent = false;
|
// overrides from @MapsId or @IdClass if needed
|
||||||
|
final boolean isComposite;
|
||||||
//Overrides from @MapsId if needed
|
final boolean isOverridden;
|
||||||
boolean isOverridden = false;
|
final AnnotatedColumn[] actualColumns;
|
||||||
if ( isId || propertyHolder.isOrWithinEmbeddedId() || propertyHolder.isInIdClass() ) {
|
if ( propertyBinder.isId() || propertyHolder.isOrWithinEmbeddedId() || propertyHolder.isInIdClass() ) {
|
||||||
//the associated entity could be using an @IdClass making the overridden property a component
|
// the associated entity could be using an @IdClass making the overridden property a component
|
||||||
PropertyData overridingProperty = getPropertyOverriddenByMapperOrMapsId(
|
final PropertyData overridingProperty = getPropertyOverriddenByMapperOrMapsId(
|
||||||
isId,
|
propertyBinder.isId(),
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
property.getName(),
|
property.getName(),
|
||||||
context
|
context
|
||||||
|
@ -1368,143 +1351,210 @@ public final class AnnotationBinder {
|
||||||
if ( overridingProperty != null ) {
|
if ( overridingProperty != null ) {
|
||||||
isOverridden = true;
|
isOverridden = true;
|
||||||
final InheritanceState state = inheritanceStatePerClass.get( overridingProperty.getClassOrElement() );
|
final InheritanceState state = inheritanceStatePerClass.get( overridingProperty.getClassOrElement() );
|
||||||
if ( state != null ) {
|
isComposite = state != null ? state.hasIdClassOrEmbeddedId() : isEmbedded( property, returnedClass );
|
||||||
isComponent = state.hasIdClassOrEmbeddedId();
|
|
||||||
}
|
|
||||||
//Get the new column
|
//Get the new column
|
||||||
columns = columnsBuilder.overrideColumnFromMapperOrMapsIdProperty(isId);
|
actualColumns = columnsBuilder.overrideColumnFromMapperOrMapsIdProperty( propertyBinder.isId() );
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isComponent = isComponent || isEmbedded( property, returnedClass );
|
|
||||||
final Class<? extends CompositeUserType<?>> compositeUserType = resolveCompositeUserType(
|
|
||||||
inferredData.getProperty(),
|
|
||||||
inferredData.getClassOrElement(),
|
|
||||||
context
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( isComponent || compositeUserType != null ) {
|
|
||||||
final String referencedEntityName;
|
|
||||||
final String propertyName;
|
|
||||||
if ( isOverridden ) {
|
|
||||||
// careful: not always a @MapsId property, sometimes it's from an @IdClass
|
|
||||||
PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
|
|
||||||
isId, propertyHolder, property.getName(), context
|
|
||||||
);
|
|
||||||
referencedEntityName = mapsIdProperty.getClassOrElementName();
|
|
||||||
propertyName = mapsIdProperty.getPropertyName();
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
referencedEntityName = null;
|
isOverridden = false;
|
||||||
propertyName = null;
|
isComposite = isEmbedded( property, returnedClass );
|
||||||
|
actualColumns = columns;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
isOverridden = false;
|
||||||
|
isComposite = isEmbedded( property, returnedClass );
|
||||||
|
actualColumns = columns;
|
||||||
|
}
|
||||||
|
|
||||||
propertyBinder = bindComponent(
|
final Class<? extends CompositeUserType<?>> compositeUserType = resolveCompositeUserType( inferredData, context );
|
||||||
inferredData,
|
|
||||||
|
if ( isComposite || compositeUserType != null ) {
|
||||||
|
propertyBinder = createCompositeBinder(
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
entityBinder.getPropertyAccessor(property),
|
inferredData,
|
||||||
entityBinder,
|
entityBinder,
|
||||||
isIdentifierMapper,
|
isIdentifierMapper,
|
||||||
context,
|
|
||||||
isComponentEmbedded,
|
isComponentEmbedded,
|
||||||
isId,
|
context,
|
||||||
inheritanceStatePerClass,
|
inheritanceStatePerClass,
|
||||||
referencedEntityName,
|
property,
|
||||||
propertyName,
|
actualColumns,
|
||||||
determineCustomInstantiator( property, returnedClass, context ),
|
returnedClass,
|
||||||
compositeUserType,
|
propertyBinder,
|
||||||
isOverridden ? (AnnotatedJoinColumn[]) columns : null
|
isOverridden,
|
||||||
|
compositeUserType
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//provide the basic property mapping
|
createBasicBinder(
|
||||||
boolean optional = true;
|
propertyHolder,
|
||||||
boolean lazy = false;
|
inferredData,
|
||||||
if ( property.isAnnotationPresent( Basic.class ) ) {
|
nullability,
|
||||||
Basic ann = property.getAnnotation( Basic.class );
|
context,
|
||||||
optional = ann.optional();
|
property,
|
||||||
lazy = ann.fetch() == FetchType.LAZY;
|
actualColumns,
|
||||||
}
|
propertyBinder,
|
||||||
//implicit type will check basic types and Serializable classes
|
isOverridden
|
||||||
if ( isId || !optional && nullability != Nullability.FORCED_NULL ) {
|
);
|
||||||
//force columns to not null
|
|
||||||
for ( AnnotatedColumn col : columns) {
|
|
||||||
if ( isId && col.isFormula() ) {
|
|
||||||
throw new CannotForceNonNullableException(
|
|
||||||
String.format(
|
|
||||||
Locale.ROOT,
|
|
||||||
"Identifier property [%s] cannot contain formula mapping [%s]",
|
|
||||||
HCANNHelper.annotatedElementSignature(property),
|
|
||||||
col.getFormulaString()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
col.forceNotNull();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
propertyBinder.setLazy( lazy );
|
|
||||||
propertyBinder.setColumns(columns);
|
|
||||||
if ( isOverridden ) {
|
|
||||||
final PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
|
|
||||||
isId, propertyHolder, property.getName(), context
|
|
||||||
);
|
|
||||||
propertyBinder.setReferencedEntityName( mapsIdProperty.getClassOrElementName() );
|
|
||||||
}
|
|
||||||
|
|
||||||
propertyBinder.makePropertyValueAndBind();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if ( isOverridden ) {
|
if ( isOverridden ) {
|
||||||
final PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
|
handleGeneratorsForOverriddenId(
|
||||||
isId, propertyHolder, property.getName(), context
|
propertyHolder,
|
||||||
|
classGenerators,
|
||||||
|
context,
|
||||||
|
property,
|
||||||
|
propertyBinder
|
||||||
);
|
);
|
||||||
final IdentifierGeneratorDefinition.Builder foreignGeneratorBuilder =
|
|
||||||
new IdentifierGeneratorDefinition.Builder();
|
|
||||||
foreignGeneratorBuilder.setName( "Hibernate-local--foreign generator" );
|
|
||||||
foreignGeneratorBuilder.setStrategy( "foreign" );
|
|
||||||
foreignGeneratorBuilder.addParam( "property", mapsIdProperty.getPropertyName() );
|
|
||||||
final IdentifierGeneratorDefinition foreignGenerator = foreignGeneratorBuilder.build();
|
|
||||||
|
|
||||||
if ( isGlobalGeneratorNameGlobal( context ) ) {
|
|
||||||
SecondPass secondPass = new IdGeneratorResolverSecondPass(
|
|
||||||
(SimpleValue) propertyBinder.getValue(),
|
|
||||||
property,
|
|
||||||
foreignGenerator.getStrategy(),
|
|
||||||
foreignGenerator.getName(),
|
|
||||||
context,
|
|
||||||
foreignGenerator
|
|
||||||
);
|
|
||||||
context.getMetadataCollector().addSecondPass( secondPass );
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Map<String, IdentifierGeneratorDefinition> localGenerators = new HashMap<>(classGenerators);
|
|
||||||
localGenerators.put( foreignGenerator.getName(), foreignGenerator );
|
|
||||||
|
|
||||||
makeIdGenerator(
|
|
||||||
(SimpleValue) propertyBinder.getValue(),
|
|
||||||
property,
|
|
||||||
foreignGenerator.getStrategy(),
|
|
||||||
foreignGenerator.getName(),
|
|
||||||
context,
|
|
||||||
localGenerators
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (isId) {
|
else if ( propertyBinder.isId() ) {
|
||||||
//components and regular basic types create SimpleValue objects
|
//components and regular basic types create SimpleValue objects
|
||||||
if ( !isOverridden ) {
|
processId(
|
||||||
processId(
|
propertyHolder,
|
||||||
propertyHolder,
|
inferredData,
|
||||||
inferredData,
|
(SimpleValue) propertyBinder.getValue(),
|
||||||
(SimpleValue) propertyBinder.getValue(),
|
classGenerators,
|
||||||
classGenerators,
|
isIdentifierMapper,
|
||||||
isIdentifierMapper,
|
context
|
||||||
context
|
);
|
||||||
);
|
}
|
||||||
|
return actualColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void handleGeneratorsForOverriddenId(
|
||||||
|
PropertyHolder propertyHolder,
|
||||||
|
Map<String, IdentifierGeneratorDefinition> classGenerators,
|
||||||
|
MetadataBuildingContext context,
|
||||||
|
XProperty property,
|
||||||
|
PropertyBinder propertyBinder) {
|
||||||
|
final PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
|
||||||
|
propertyBinder.isId(), propertyHolder, property.getName(), context
|
||||||
|
);
|
||||||
|
final IdentifierGeneratorDefinition.Builder foreignGeneratorBuilder =
|
||||||
|
new IdentifierGeneratorDefinition.Builder();
|
||||||
|
foreignGeneratorBuilder.setName( "Hibernate-local--foreign generator" );
|
||||||
|
foreignGeneratorBuilder.setStrategy( "foreign" );
|
||||||
|
foreignGeneratorBuilder.addParam( "property", mapsIdProperty.getPropertyName() );
|
||||||
|
final IdentifierGeneratorDefinition foreignGenerator = foreignGeneratorBuilder.build();
|
||||||
|
if ( isGlobalGeneratorNameGlobal(context) ) {
|
||||||
|
SecondPass secondPass = new IdGeneratorResolverSecondPass(
|
||||||
|
(SimpleValue) propertyBinder.getValue(),
|
||||||
|
property,
|
||||||
|
foreignGenerator.getStrategy(),
|
||||||
|
foreignGenerator.getName(),
|
||||||
|
context,
|
||||||
|
foreignGenerator
|
||||||
|
);
|
||||||
|
context.getMetadataCollector().addSecondPass( secondPass );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
final Map<String, IdentifierGeneratorDefinition> localGenerators = new HashMap<>(classGenerators);
|
||||||
|
localGenerators.put( foreignGenerator.getName(), foreignGenerator );
|
||||||
|
makeIdGenerator(
|
||||||
|
(SimpleValue) propertyBinder.getValue(),
|
||||||
|
property,
|
||||||
|
foreignGenerator.getStrategy(),
|
||||||
|
foreignGenerator.getName(),
|
||||||
|
context,
|
||||||
|
localGenerators
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void createBasicBinder(
|
||||||
|
PropertyHolder propertyHolder,
|
||||||
|
PropertyData inferrredData,
|
||||||
|
Nullability nullability,
|
||||||
|
MetadataBuildingContext context,
|
||||||
|
XProperty property,
|
||||||
|
AnnotatedColumn[] columns,
|
||||||
|
PropertyBinder propertyBinder,
|
||||||
|
boolean isOverridden) {
|
||||||
|
//provide the basic property mapping
|
||||||
|
final boolean optional;
|
||||||
|
final boolean lazy;
|
||||||
|
if ( property.isAnnotationPresent( Basic.class ) ) {
|
||||||
|
Basic ann = property.getAnnotation( Basic.class );
|
||||||
|
optional = ann.optional();
|
||||||
|
lazy = ann.fetch() == FetchType.LAZY;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
optional = true;
|
||||||
|
lazy = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//implicit type will check basic types and Serializable classes
|
||||||
|
if ( propertyBinder.isId() || !optional && nullability != Nullability.FORCED_NULL ) {
|
||||||
|
//force columns to not null
|
||||||
|
for ( AnnotatedColumn col : columns ) {
|
||||||
|
if ( propertyBinder.isId() && col.isFormula() ) {
|
||||||
|
throw new CannotForceNonNullableException( "Identifier property '"
|
||||||
|
+ getPath( propertyHolder, inferrredData ) + "' cannot map to a '@Formula'" );
|
||||||
|
}
|
||||||
|
col.forceNotNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return columns;
|
|
||||||
|
propertyBinder.setLazy( lazy );
|
||||||
|
propertyBinder.setColumns( columns );
|
||||||
|
if (isOverridden) {
|
||||||
|
final PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
|
||||||
|
propertyBinder.isId(), propertyHolder, property.getName(), context
|
||||||
|
);
|
||||||
|
propertyBinder.setReferencedEntityName( mapsIdProperty.getClassOrElementName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
propertyBinder.makePropertyValueAndBind();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PropertyBinder createCompositeBinder(
|
||||||
|
PropertyHolder propertyHolder,
|
||||||
|
PropertyData inferredData,
|
||||||
|
EntityBinder entityBinder,
|
||||||
|
boolean isIdentifierMapper,
|
||||||
|
boolean isComponentEmbedded,
|
||||||
|
MetadataBuildingContext context,
|
||||||
|
Map<XClass, InheritanceState> inheritanceStatePerClass,
|
||||||
|
XProperty property,
|
||||||
|
AnnotatedColumn[] columns,
|
||||||
|
XClass returnedClass,
|
||||||
|
PropertyBinder propertyBinder,
|
||||||
|
boolean isOverridden,
|
||||||
|
Class<? extends CompositeUserType<?>> compositeUserType) {
|
||||||
|
final String referencedEntityName;
|
||||||
|
final String propertyName;
|
||||||
|
final AnnotatedJoinColumn[] actualColumns;
|
||||||
|
if ( isOverridden ) {
|
||||||
|
// careful: not always a @MapsId property, sometimes it's from an @IdClass
|
||||||
|
PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
|
||||||
|
propertyBinder.isId(), propertyHolder, property.getName(), context
|
||||||
|
);
|
||||||
|
referencedEntityName = mapsIdProperty.getClassOrElementName();
|
||||||
|
propertyName = mapsIdProperty.getPropertyName();
|
||||||
|
actualColumns = (AnnotatedJoinColumn[]) columns;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
referencedEntityName = null;
|
||||||
|
propertyName = null;
|
||||||
|
actualColumns = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return bindComponent(
|
||||||
|
inferredData,
|
||||||
|
propertyHolder,
|
||||||
|
entityBinder.getPropertyAccessor( property ),
|
||||||
|
entityBinder,
|
||||||
|
isIdentifierMapper,
|
||||||
|
context,
|
||||||
|
isComponentEmbedded,
|
||||||
|
propertyBinder.isId(),
|
||||||
|
inheritanceStatePerClass,
|
||||||
|
referencedEntityName,
|
||||||
|
propertyName,
|
||||||
|
determineCustomInstantiator( property, returnedClass, context ),
|
||||||
|
compositeUserType,
|
||||||
|
actualColumns
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isEmbedded(XProperty property, XClass returnedClass) {
|
private static boolean isEmbedded(XProperty property, XClass returnedClass) {
|
||||||
|
@ -1759,9 +1809,11 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Class<? extends CompositeUserType<?>> resolveCompositeUserType(
|
private static Class<? extends CompositeUserType<?>> resolveCompositeUserType(
|
||||||
XProperty property,
|
PropertyData inferredData,
|
||||||
XClass returnedClass,
|
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
|
final XProperty property = inferredData.getProperty();
|
||||||
|
final XClass returnedClass = inferredData.getClassOrElement();
|
||||||
|
|
||||||
if ( property != null ) {
|
if ( property != null ) {
|
||||||
final CompositeType compositeType = property.getAnnotation( CompositeType.class );
|
final CompositeType compositeType = property.getAnnotation( CompositeType.class );
|
||||||
if ( compositeType != null ) {
|
if ( compositeType != null ) {
|
||||||
|
@ -1941,9 +1993,9 @@ public final class AnnotationBinder {
|
||||||
Class<? extends EmbeddableInstantiator> customInstantiatorImpl,
|
Class<? extends EmbeddableInstantiator> customInstantiatorImpl,
|
||||||
Class<? extends CompositeUserType<?>> compositeUserTypeClass,
|
Class<? extends CompositeUserType<?>> compositeUserTypeClass,
|
||||||
AnnotatedJoinColumn[] columns) {
|
AnnotatedJoinColumn[] columns) {
|
||||||
Component comp;
|
final Component component;
|
||||||
if ( referencedEntityName != null ) {
|
if ( referencedEntityName != null ) {
|
||||||
comp = createComponent(
|
component = createComponent(
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
inferredData,
|
inferredData,
|
||||||
isComponentEmbedded,
|
isComponentEmbedded,
|
||||||
|
@ -1952,7 +2004,7 @@ public final class AnnotationBinder {
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
SecondPass sp = new CopyIdentifierComponentSecondPass(
|
SecondPass sp = new CopyIdentifierComponentSecondPass(
|
||||||
comp,
|
component,
|
||||||
referencedEntityName,
|
referencedEntityName,
|
||||||
propertyName,
|
propertyName,
|
||||||
columns,
|
columns,
|
||||||
|
@ -1961,7 +2013,7 @@ public final class AnnotationBinder {
|
||||||
buildingContext.getMetadataCollector().addSecondPass( sp );
|
buildingContext.getMetadataCollector().addSecondPass( sp );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
comp = fillComponent(
|
component = fillComponent(
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
inferredData,
|
inferredData,
|
||||||
propertyAccessor,
|
propertyAccessor,
|
||||||
|
@ -1977,18 +2029,18 @@ public final class AnnotationBinder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( isId ) {
|
if ( isId ) {
|
||||||
comp.setKey( true );
|
component.setKey( true );
|
||||||
if ( propertyHolder.getPersistentClass().getIdentifier() != null ) {
|
if ( propertyHolder.getPersistentClass().getIdentifier() != null ) {
|
||||||
throw new AnnotationException(
|
throw new AnnotationException(
|
||||||
"Embeddable class '" + comp.getComponentClassName()
|
"Embeddable class '" + component.getComponentClassName()
|
||||||
+ "' may not have a property annotated '@Id' since it is used by '"
|
+ "' may not have a property annotated '@Id' since it is used by '"
|
||||||
+ getPath( propertyHolder, inferredData )
|
+ getPath( propertyHolder, inferredData )
|
||||||
+ "' as an '@EmbeddedId'"
|
+ "' as an '@EmbeddedId'"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if ( referencedEntityName == null && comp.getPropertySpan() == 0 ) {
|
if ( referencedEntityName == null && component.getPropertySpan() == 0 ) {
|
||||||
throw new AnnotationException(
|
throw new AnnotationException(
|
||||||
"Embeddable class '" + comp.getComponentClassName()
|
"Embeddable class '" + component.getComponentClassName()
|
||||||
+ "' may not be used as an '@EmbeddedId' by '"
|
+ "' may not be used as an '@EmbeddedId' by '"
|
||||||
+ getPath( propertyHolder, inferredData )
|
+ getPath( propertyHolder, inferredData )
|
||||||
+ "' because it has no properties"
|
+ "' because it has no properties"
|
||||||
|
@ -1996,9 +2048,9 @@ public final class AnnotationBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PropertyBinder binder = new PropertyBinder();
|
PropertyBinder binder = new PropertyBinder();
|
||||||
binder.setDeclaringClass(inferredData.getDeclaringClass());
|
binder.setDeclaringClass( inferredData.getDeclaringClass() );
|
||||||
binder.setName( inferredData.getPropertyName() );
|
binder.setName( inferredData.getPropertyName() );
|
||||||
binder.setValue( comp );
|
binder.setValue( component );
|
||||||
binder.setProperty( inferredData.getProperty() );
|
binder.setProperty( inferredData.getProperty() );
|
||||||
binder.setAccessType( inferredData.getDefaultAccess() );
|
binder.setAccessType( inferredData.getDefaultAccess() );
|
||||||
binder.setEmbedded( isComponentEmbedded );
|
binder.setEmbedded( isComponentEmbedded );
|
||||||
|
|
|
@ -163,6 +163,7 @@ public class BinderHelper {
|
||||||
//associated entity only used for more precise exception
|
//associated entity only used for more precise exception
|
||||||
PersistentClass associatedEntity,
|
PersistentClass associatedEntity,
|
||||||
Value value,
|
Value value,
|
||||||
|
//true when we do the reverse side of a @ManyToMany
|
||||||
boolean inverse,
|
boolean inverse,
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
|
|
||||||
|
@ -173,7 +174,7 @@ public class BinderHelper {
|
||||||
final AnnotatedJoinColumn firstColumn = columns[0];
|
final AnnotatedJoinColumn firstColumn = columns[0];
|
||||||
if ( !firstColumn.isImplicit()
|
if ( !firstColumn.isImplicit()
|
||||||
// only necessary for owning side of association
|
// only necessary for owning side of association
|
||||||
&& isEmpty( firstColumn.getMappedBy() )
|
&& !firstColumn.hasMappedBy()
|
||||||
// not necessary for a primary key reference
|
// not necessary for a primary key reference
|
||||||
&& checkReferencedColumnsType( columns, ownerEntity, context ) == NON_PK_REFERENCE ) {
|
&& checkReferencedColumnsType( columns, ownerEntity, context ) == NON_PK_REFERENCE ) {
|
||||||
|
|
||||||
|
@ -301,7 +302,7 @@ public class BinderHelper {
|
||||||
String syntheticPropertyName =
|
String syntheticPropertyName =
|
||||||
"_" + associatedClass.getEntityName().replace('.', '_') +
|
"_" + associatedClass.getEntityName().replace('.', '_') +
|
||||||
"_" + propertyName.replace('.', '_');
|
"_" + propertyName.replace('.', '_');
|
||||||
if (inverse) {
|
if ( inverse ) {
|
||||||
// Use a different name for inverse synthetic properties to avoid duplicate properties for self-referencing models
|
// Use a different name for inverse synthetic properties to avoid duplicate properties for self-referencing models
|
||||||
syntheticPropertyName += "_inverse";
|
syntheticPropertyName += "_inverse";
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@ package org.hibernate.cfg;
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates an internal attempt to mark a column as non-nullable (because its part
|
* Indicates an internal attempt to mark a column as non-nullable
|
||||||
* of a PK, etc) but we cannot force that column to be non-nullable.
|
* (because it's part of a primary key, for example) when we cannot
|
||||||
* <p/>
|
* force that column to be non-nullable. This usually indicates that
|
||||||
* Typically this indicates that the "column" is actually a formula.
|
* the "column" is actually a formula.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -79,7 +79,7 @@ class ColumnsBuilder {
|
||||||
|
|
||||||
public ColumnsBuilder extractMetadata() {
|
public ColumnsBuilder extractMetadata() {
|
||||||
columns = null;
|
columns = null;
|
||||||
joinColumns = buildExplicitJoinColumns(property, inferredData);
|
joinColumns = buildExplicitJoinColumns( property, inferredData );
|
||||||
|
|
||||||
|
|
||||||
Comment comment = property.getAnnotation(Comment.class);
|
Comment comment = property.getAnnotation(Comment.class);
|
||||||
|
@ -164,7 +164,7 @@ class ColumnsBuilder {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnotatedJoinColumn[] buildDefaultJoinColumnsForXToOne(XProperty property, PropertyData inferredData) {
|
private AnnotatedJoinColumn[] buildDefaultJoinColumnsForXToOne(XProperty property, PropertyData inferredData) {
|
||||||
AnnotatedJoinColumn[] joinColumns;
|
AnnotatedJoinColumn[] joinColumns;
|
||||||
JoinTable joinTableAnn = propertyHolder.getJoinTable( property );
|
JoinTable joinTableAnn = propertyHolder.getJoinTable( property );
|
||||||
Comment comment = property.getAnnotation(Comment.class);
|
Comment comment = property.getAnnotation(Comment.class);
|
||||||
|
@ -201,23 +201,10 @@ class ColumnsBuilder {
|
||||||
return joinColumns;
|
return joinColumns;
|
||||||
}
|
}
|
||||||
|
|
||||||
AnnotatedJoinColumn[] buildExplicitJoinColumns(XProperty property, PropertyData inferredData) {
|
private AnnotatedJoinColumn[] buildExplicitJoinColumns(XProperty property, PropertyData inferredData) {
|
||||||
//process @JoinColumn(s) before @Column(s) to handle collection of entities properly
|
// process @JoinColumns before @Columns to handle collection of entities properly
|
||||||
JoinColumn[] joinColumnAnnotations = null;
|
|
||||||
|
|
||||||
if ( property.isAnnotationPresent( JoinColumn.class ) ) {
|
|
||||||
joinColumnAnnotations = new JoinColumn[] { property.getAnnotation( JoinColumn.class ) };
|
|
||||||
}
|
|
||||||
else if ( property.isAnnotationPresent( JoinColumns.class ) ) {
|
|
||||||
JoinColumns joinColumnAnnotation = property.getAnnotation( JoinColumns.class );
|
|
||||||
joinColumnAnnotations = joinColumnAnnotation.value();
|
|
||||||
int length = joinColumnAnnotations.length;
|
|
||||||
if ( length == 0 ) {
|
|
||||||
throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
|
|
||||||
+ "' has an empty '@JoinColumns' annotation" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
final JoinColumn[] joinColumnAnnotations = getJoinColumnAnnotations(property, inferredData);
|
||||||
if ( joinColumnAnnotations != null ) {
|
if ( joinColumnAnnotations != null ) {
|
||||||
return AnnotatedJoinColumn.buildJoinColumns(
|
return AnnotatedJoinColumn.buildJoinColumns(
|
||||||
joinColumnAnnotations,
|
joinColumnAnnotations,
|
||||||
|
@ -230,24 +217,8 @@ class ColumnsBuilder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
JoinColumnOrFormula[] joinColumnOrFormulaAnnotations = null;
|
final JoinColumnOrFormula[] joinColumnOrFormulaAnnotations = joinColumnOrFormulaAnnotations( property, inferredData );
|
||||||
|
if ( joinColumnOrFormulaAnnotations != null ) {
|
||||||
if ( property.isAnnotationPresent( JoinColumnOrFormula.class ) ) {
|
|
||||||
joinColumnOrFormulaAnnotations = new JoinColumnOrFormula[] {
|
|
||||||
property.getAnnotation( JoinColumnOrFormula.class ) };
|
|
||||||
}
|
|
||||||
else if ( property.isAnnotationPresent( JoinColumnsOrFormulas.class ) ) {
|
|
||||||
JoinColumnsOrFormulas joinColumnsOrFormulasAnnotations = property.getAnnotation(
|
|
||||||
JoinColumnsOrFormulas.class );
|
|
||||||
joinColumnOrFormulaAnnotations = joinColumnsOrFormulasAnnotations.value();
|
|
||||||
int length = joinColumnOrFormulaAnnotations.length;
|
|
||||||
if ( length == 0 ) {
|
|
||||||
throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
|
|
||||||
+ "' has an empty '@JoinColumnsOrFormulas' annotation" );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (joinColumnOrFormulaAnnotations != null) {
|
|
||||||
return AnnotatedJoinColumn.buildJoinColumnsOrFormulas(
|
return AnnotatedJoinColumn.buildJoinColumnsOrFormulas(
|
||||||
joinColumnOrFormulaAnnotations,
|
joinColumnOrFormulaAnnotations,
|
||||||
null,
|
null,
|
||||||
|
@ -258,12 +229,11 @@ class ColumnsBuilder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property.isAnnotationPresent( JoinFormula.class)) {
|
if ( property.isAnnotationPresent( JoinFormula.class) ) {
|
||||||
JoinFormula ann = getOverridableAnnotation( property, JoinFormula.class, buildingContext );
|
final JoinFormula joinFormula = getOverridableAnnotation( property, JoinFormula.class, buildingContext );
|
||||||
AnnotatedJoinColumn[] annotatedJoinColumns = new AnnotatedJoinColumn[1];
|
final AnnotatedJoinColumn[] annotatedJoinColumns = new AnnotatedJoinColumn[1];
|
||||||
annotatedJoinColumns[0] = AnnotatedJoinColumn.buildJoinFormula(
|
annotatedJoinColumns[0] = AnnotatedJoinColumn.buildJoinFormula(
|
||||||
ann,
|
joinFormula,
|
||||||
null,
|
|
||||||
entityBinder.getSecondaryTables(),
|
entityBinder.getSecondaryTables(),
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
inferredData.getPropertyName(),
|
inferredData.getPropertyName(),
|
||||||
|
@ -275,29 +245,57 @@ class ColumnsBuilder {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JoinColumnOrFormula[] joinColumnOrFormulaAnnotations(XProperty property, PropertyData inferredData) {
|
||||||
|
if ( property.isAnnotationPresent( JoinColumnOrFormula.class ) ) {
|
||||||
|
return new JoinColumnOrFormula[] { property.getAnnotation( JoinColumnOrFormula.class ) };
|
||||||
|
}
|
||||||
|
else if ( property.isAnnotationPresent( JoinColumnsOrFormulas.class ) ) {
|
||||||
|
JoinColumnsOrFormulas joinColumnsOrFormulasAnnotations = property.getAnnotation( JoinColumnsOrFormulas.class );
|
||||||
|
final JoinColumnOrFormula[] joinColumnOrFormulaAnnotations = joinColumnsOrFormulasAnnotations.value();
|
||||||
|
if ( joinColumnOrFormulaAnnotations.length == 0 ) {
|
||||||
|
throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData)
|
||||||
|
+ "' has an empty '@JoinColumnsOrFormulas' annotation" );
|
||||||
|
}
|
||||||
|
return joinColumnOrFormulaAnnotations;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private JoinColumn[] getJoinColumnAnnotations(XProperty property, PropertyData inferredData) {
|
||||||
|
if ( property.isAnnotationPresent( JoinColumn.class ) ) {
|
||||||
|
return new JoinColumn[] { property.getAnnotation( JoinColumn.class ) };
|
||||||
|
}
|
||||||
|
else if ( property.isAnnotationPresent( JoinColumns.class ) ) {
|
||||||
|
final JoinColumns joinColumnAnnotation = property.getAnnotation( JoinColumns.class );
|
||||||
|
final JoinColumn[] joinColumnAnnotations = joinColumnAnnotation.value();
|
||||||
|
if ( joinColumnAnnotations.length == 0 ) {
|
||||||
|
throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData)
|
||||||
|
+ "' has an empty '@JoinColumns' annotation" );
|
||||||
|
}
|
||||||
|
return joinColumnAnnotations;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AnnotatedColumn[] overrideColumnFromMapperOrMapsIdProperty(boolean isId) {
|
AnnotatedColumn[] overrideColumnFromMapperOrMapsIdProperty(boolean isId) {
|
||||||
AnnotatedColumn[] result = columns;
|
|
||||||
final PropertyData overridingProperty = getPropertyOverriddenByMapperOrMapsId(
|
final PropertyData overridingProperty = getPropertyOverriddenByMapperOrMapsId(
|
||||||
isId,
|
isId,
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
property.getName(),
|
property.getName(),
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
if ( overridingProperty != null ) {
|
return overridingProperty != null ? buildExplicitOrDefaultJoinColumn( overridingProperty ) : columns;
|
||||||
result = buildExcplicitOrDefaultJoinColumn( overridingProperty );
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* useful to override a column either by @MapsId or by @IdClass
|
* useful to override a column either by @MapsId or by @IdClass
|
||||||
*/
|
*/
|
||||||
AnnotatedColumn[] buildExcplicitOrDefaultJoinColumn(PropertyData overridingProperty) {
|
private AnnotatedColumn[] buildExplicitOrDefaultJoinColumn(PropertyData overridingProperty) {
|
||||||
AnnotatedColumn[] result;
|
final AnnotatedColumn[] columns = buildExplicitJoinColumns( overridingProperty.getProperty(), overridingProperty );
|
||||||
result = buildExplicitJoinColumns( overridingProperty.getProperty(), overridingProperty );
|
return columns == null ? buildDefaultJoinColumnsForXToOne( overridingProperty.getProperty(), overridingProperty ) : columns;
|
||||||
if (result == null) {
|
|
||||||
result = buildDefaultJoinColumnsForXToOne( overridingProperty.getProperty(), overridingProperty);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,38 +22,10 @@ import static org.hibernate.cfg.BinderHelper.isEmptyAnnotationValue;
|
||||||
public class IndexColumn extends AnnotatedColumn {
|
public class IndexColumn extends AnnotatedColumn {
|
||||||
private int base;
|
private int base;
|
||||||
|
|
||||||
// TODO move to a getter setter strategy for readability
|
public IndexColumn() {
|
||||||
public IndexColumn(
|
setLength( 0L );
|
||||||
boolean isImplicit,
|
setPrecision( 0 );
|
||||||
String sqlType,
|
setScale( 0 );
|
||||||
long length,
|
|
||||||
int precision,
|
|
||||||
int scale,
|
|
||||||
String name,
|
|
||||||
boolean nullable,
|
|
||||||
boolean unique,
|
|
||||||
boolean insertable,
|
|
||||||
boolean updatable,
|
|
||||||
String secondaryTableName,
|
|
||||||
Map<String, Join> joins,
|
|
||||||
PropertyHolder propertyHolder,
|
|
||||||
MetadataBuildingContext buildingContext) {
|
|
||||||
super();
|
|
||||||
setImplicit( isImplicit );
|
|
||||||
setSqlType( sqlType );
|
|
||||||
setLength( length );
|
|
||||||
setPrecision( precision );
|
|
||||||
setScale( scale );
|
|
||||||
setLogicalColumnName( name );
|
|
||||||
setNullable( nullable );
|
|
||||||
setUnique( unique );
|
|
||||||
setInsertable( insertable );
|
|
||||||
setUpdatable( updatable );
|
|
||||||
setExplicitTableName( secondaryTableName );
|
|
||||||
setPropertyHolder( propertyHolder );
|
|
||||||
setJoins( joins );
|
|
||||||
setBuildingContext( buildingContext );
|
|
||||||
bind();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IndexColumn fromAnnotations(
|
public static IndexColumn fromAnnotations(
|
||||||
|
@ -64,9 +36,9 @@ public class IndexColumn extends AnnotatedColumn {
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
Map<String, Join> secondaryTables,
|
Map<String, Join> secondaryTables,
|
||||||
MetadataBuildingContext context) {
|
MetadataBuildingContext context) {
|
||||||
final IndexColumn indexColumn;
|
final IndexColumn column;
|
||||||
if ( jpaAnnotation != null ) {
|
if ( jpaAnnotation != null ) {
|
||||||
indexColumn = buildColumnFromAnnotation(
|
column = buildColumnFromAnnotation(
|
||||||
jpaAnnotation,
|
jpaAnnotation,
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
inferredData,
|
inferredData,
|
||||||
|
@ -75,39 +47,28 @@ public class IndexColumn extends AnnotatedColumn {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if ( hibAnnotation != null ) {
|
else if ( hibAnnotation != null ) {
|
||||||
indexColumn = buildColumnFromAnnotation(
|
column = buildColumnFromAnnotation(
|
||||||
hibAnnotation,
|
hibAnnotation,
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
inferredData,
|
inferredData,
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
indexColumn.setBase( hibAnnotation.base() );
|
column.setBase( hibAnnotation.base() );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
indexColumn = new IndexColumn(
|
column = new IndexColumn();
|
||||||
true,
|
column.setLogicalColumnName( inferredData.getPropertyName() + "_ORDER" ); //JPA default name
|
||||||
null,
|
column.setImplicit( true );
|
||||||
0,
|
column.setBuildingContext( context );
|
||||||
0,
|
column.setPropertyHolder( propertyHolder );
|
||||||
0,
|
column.bind();
|
||||||
// Use the JPA default name...
|
|
||||||
inferredData.getPropertyName() + "_ORDER",
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
propertyHolder,
|
|
||||||
context
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( indexBaseAnnotation != null ) {
|
if ( indexBaseAnnotation != null ) {
|
||||||
indexColumn.setBase( indexBaseAnnotation.value() );
|
column.setBase( indexBaseAnnotation.value() );
|
||||||
}
|
}
|
||||||
|
|
||||||
return indexColumn;
|
return column;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getBase() {
|
public int getBase() {
|
||||||
|
@ -134,54 +95,30 @@ public class IndexColumn extends AnnotatedColumn {
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
Map<String, Join> secondaryTables,
|
Map<String, Join> secondaryTables,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
final IndexColumn column;
|
|
||||||
if ( ann != null ) {
|
if ( ann != null ) {
|
||||||
final String sqlType = isEmptyAnnotationValue( ann.columnDefinition() ) ? null : ann.columnDefinition();
|
final String sqlType = isEmptyAnnotationValue( ann.columnDefinition() ) ? null : ann.columnDefinition();
|
||||||
final String name = isEmptyAnnotationValue( ann.name() ) ? inferredData.getPropertyName() + "_ORDER" : ann.name();
|
final String name = isEmptyAnnotationValue( ann.name() ) ? inferredData.getPropertyName() + "_ORDER" : ann.name();
|
||||||
//TODO move it to a getter based system and remove the constructor
|
//TODO move it to a getter based system and remove the constructor
|
||||||
// The JPA OrderColumn annotation defines no table element...
|
final IndexColumn column = new IndexColumn();
|
||||||
// column = new IndexColumn(
|
column.setLogicalColumnName( name );
|
||||||
// false, sqlType, 0, 0, 0, name, ann.nullable(),
|
column.setSqlType( sqlType );
|
||||||
// false, ann.insertable(), ann.updatable(), ann.table(),
|
column.setNullable( ann.nullable() );
|
||||||
// secondaryTables, propertyHolder, mappings
|
column.setJoins( secondaryTables );
|
||||||
// );
|
column.setInsertable( ann.insertable() );
|
||||||
column = new IndexColumn(
|
column.setUpdatable( ann.updatable() );
|
||||||
false,
|
column.setBuildingContext( buildingContext );
|
||||||
sqlType,
|
column.setPropertyHolder( propertyHolder );
|
||||||
0,
|
column.bind();
|
||||||
0,
|
return column;
|
||||||
0,
|
|
||||||
name,
|
|
||||||
ann.nullable(),
|
|
||||||
false,
|
|
||||||
ann.insertable(),
|
|
||||||
ann.updatable(),
|
|
||||||
//ann.table()
|
|
||||||
null,
|
|
||||||
secondaryTables,
|
|
||||||
propertyHolder,
|
|
||||||
buildingContext
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
column = new IndexColumn(
|
final IndexColumn column = new IndexColumn();
|
||||||
true,
|
column.setImplicit( true );
|
||||||
null,
|
column.setBuildingContext( buildingContext );
|
||||||
0,
|
column.setPropertyHolder( propertyHolder );
|
||||||
0,
|
column.bind();
|
||||||
0,
|
return column;
|
||||||
null,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
propertyHolder,
|
|
||||||
buildingContext
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -198,47 +135,27 @@ public class IndexColumn extends AnnotatedColumn {
|
||||||
PropertyHolder propertyHolder,
|
PropertyHolder propertyHolder,
|
||||||
PropertyData inferredData,
|
PropertyData inferredData,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
final IndexColumn column;
|
|
||||||
if ( ann != null ) {
|
if ( ann != null ) {
|
||||||
final String sqlType = isEmptyAnnotationValue( ann.columnDefinition() ) ? null : ann.columnDefinition();
|
final String sqlType = isEmptyAnnotationValue( ann.columnDefinition() ) ? null : ann.columnDefinition();
|
||||||
final String name = isEmptyAnnotationValue( ann.name() ) ? inferredData.getPropertyName() : ann.name();
|
final String name = isEmptyAnnotationValue( ann.name() ) ? inferredData.getPropertyName() : ann.name();
|
||||||
//TODO move it to a getter based system and remove the constructor
|
//TODO move it to a getter based system and remove the constructor
|
||||||
column = new IndexColumn(
|
final IndexColumn column = new IndexColumn();
|
||||||
false,
|
column.setLogicalColumnName( name );
|
||||||
sqlType,
|
column.setSqlType( sqlType );
|
||||||
0,
|
column.setNullable( ann.nullable() );
|
||||||
0,
|
|
||||||
0,
|
|
||||||
name,
|
|
||||||
ann.nullable(),
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
propertyHolder,
|
|
||||||
buildingContext
|
|
||||||
);
|
|
||||||
column.setBase( ann.base() );
|
column.setBase( ann.base() );
|
||||||
|
column.setBuildingContext( buildingContext );
|
||||||
|
column.setPropertyHolder( propertyHolder );
|
||||||
|
column.bind();
|
||||||
|
return column;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
column = new IndexColumn(
|
final IndexColumn column = new IndexColumn();
|
||||||
true,
|
column.setImplicit( true );
|
||||||
null,
|
column.setBuildingContext( buildingContext );
|
||||||
0,
|
column.setPropertyHolder( propertyHolder );
|
||||||
0,
|
column.bind();
|
||||||
0,
|
return column;
|
||||||
null,
|
|
||||||
true,
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
propertyHolder,
|
|
||||||
buildingContext
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return column;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,18 +90,16 @@ public class ToOneFkSecondPass extends FkSecondPass {
|
||||||
|
|
||||||
public void doSecondPass(java.util.Map<String, PersistentClass> persistentClasses) throws MappingException {
|
public void doSecondPass(java.util.Map<String, PersistentClass> persistentClasses) throws MappingException {
|
||||||
if ( value instanceof ManyToOne ) {
|
if ( value instanceof ManyToOne ) {
|
||||||
ManyToOne manyToOne = (ManyToOne) value;
|
final ManyToOne manyToOne = (ManyToOne) value;
|
||||||
PersistentClass ref = persistentClasses.get( manyToOne.getReferencedEntityName() );
|
final PersistentClass referencedEntity = persistentClasses.get( manyToOne.getReferencedEntityName() );
|
||||||
if ( ref == null ) {
|
if ( referencedEntity == null ) {
|
||||||
throw new AnnotationException( "Association '" + StringHelper.qualify( entityClassName, path )
|
throw new AnnotationException( "Association '" + StringHelper.qualify( entityClassName, path )
|
||||||
+ "' targets an unknown entity named '" + manyToOne.getReferencedEntityName() + "'" );
|
+ "' targets an unknown entity named '" + manyToOne.getReferencedEntityName() + "'" );
|
||||||
}
|
}
|
||||||
manyToOne.setPropertyName( path );
|
manyToOne.setPropertyName( path );
|
||||||
createSyntheticPropertyReference( columns, ref, null, manyToOne, false, buildingContext );
|
createSyntheticPropertyReference( columns, referencedEntity, null, manyToOne, false, buildingContext );
|
||||||
TableBinder.bindForeignKey( ref, null, columns, manyToOne, unique, buildingContext );
|
TableBinder.bindForeignKey( referencedEntity, null, columns, manyToOne, unique, buildingContext );
|
||||||
/*
|
// HbmMetadataSourceProcessorImpl does this only when property-ref != null, but IMO, it makes sense event if it is null
|
||||||
* HbmMetadataSourceProcessorImpl does this only when property-ref != null, but IMO, it makes sense event if it is null
|
|
||||||
*/
|
|
||||||
if ( !manyToOne.isIgnoreNotFound() ) manyToOne.createPropertyRefConstraints( persistentClasses );
|
if ( !manyToOne.isIgnoreNotFound() ) manyToOne.createPropertyRefConstraints( persistentClasses );
|
||||||
}
|
}
|
||||||
else if ( value instanceof OneToOne ) {
|
else if ( value instanceof OneToOne ) {
|
||||||
|
|
|
@ -178,7 +178,6 @@ import static org.hibernate.internal.util.StringHelper.qualify;
|
||||||
* @author inger
|
* @author inger
|
||||||
* @author Emmanuel Bernard
|
* @author Emmanuel Bernard
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public abstract class CollectionBinder {
|
public abstract class CollectionBinder {
|
||||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, CollectionBinder.class.getName());
|
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, CollectionBinder.class.getName());
|
||||||
|
|
||||||
|
@ -284,7 +283,7 @@ public abstract class CollectionBinder {
|
||||||
context
|
context
|
||||||
);
|
);
|
||||||
|
|
||||||
CollectionBinder collectionBinder = getCollectionBinder( property, hasMapKeyAnnotation( property ), context );
|
final CollectionBinder collectionBinder = getCollectionBinder( property, hasMapKeyAnnotation( property ), context );
|
||||||
collectionBinder.setIndexColumn( indexColumn );
|
collectionBinder.setIndexColumn( indexColumn );
|
||||||
collectionBinder.setMapKey( property.getAnnotation( MapKey.class ) );
|
collectionBinder.setMapKey( property.getAnnotation( MapKey.class ) );
|
||||||
collectionBinder.setPropertyName( inferredData.getPropertyName() );
|
collectionBinder.setPropertyName( inferredData.getPropertyName() );
|
||||||
|
@ -315,7 +314,7 @@ public abstract class CollectionBinder {
|
||||||
final PropertyData virtualProperty = property.isAnnotationPresent( ElementCollection.class )
|
final PropertyData virtualProperty = property.isAnnotationPresent( ElementCollection.class )
|
||||||
? inferredData
|
? inferredData
|
||||||
: new WrappedInferredData( inferredData, "element" );
|
: new WrappedInferredData( inferredData, "element" );
|
||||||
final Comment comment = property.getAnnotation(Comment.class);
|
final Comment comment = property.getAnnotation( Comment.class );
|
||||||
final AnnotatedColumn[] elementColumns = elementColumns(
|
final AnnotatedColumn[] elementColumns = elementColumns(
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
nullability,
|
nullability,
|
||||||
|
@ -427,12 +426,12 @@ public abstract class CollectionBinder {
|
||||||
collectionBinder.setOneToMany( true );
|
collectionBinder.setOneToMany( true );
|
||||||
}
|
}
|
||||||
else if ( elementCollectionAnn != null ) {
|
else if ( elementCollectionAnn != null ) {
|
||||||
for ( AnnotatedJoinColumn column : joinColumns) {
|
for ( AnnotatedJoinColumn column : joinColumns ) {
|
||||||
if ( column.isSecondary() ) {
|
if ( column.isSecondary() ) {
|
||||||
throw new NotYetImplementedException( "Collections having FK in secondary table" );
|
throw new NotYetImplementedException( "Collections having FK in secondary table" );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
collectionBinder.setFkJoinColumns(joinColumns);
|
collectionBinder.setFkJoinColumns( joinColumns );
|
||||||
mappedBy = "";
|
mappedBy = "";
|
||||||
final Class<?> targetElement = elementCollectionAnn.targetClass();
|
final Class<?> targetElement = elementCollectionAnn.targetClass();
|
||||||
collectionBinder.setTargetEntity( reflectionManager.toXClass( targetElement ) );
|
collectionBinder.setTargetEntity( reflectionManager.toXClass( targetElement ) );
|
||||||
|
@ -462,19 +461,21 @@ public abstract class CollectionBinder {
|
||||||
|
|
||||||
private static boolean hasMapKeyAnnotation(XProperty property) {
|
private static boolean hasMapKeyAnnotation(XProperty property) {
|
||||||
return property.isAnnotationPresent(MapKeyJavaType.class)
|
return property.isAnnotationPresent(MapKeyJavaType.class)
|
||||||
|| property.isAnnotationPresent(MapKeyJdbcType.class)
|
|| property.isAnnotationPresent(MapKeyJdbcType.class)
|
||||||
|| property.isAnnotationPresent(MapKeyJdbcTypeCode.class)
|
|| property.isAnnotationPresent(MapKeyJdbcTypeCode.class)
|
||||||
|| property.isAnnotationPresent(MapKeyMutability.class)
|
|| property.isAnnotationPresent(MapKeyMutability.class)
|
||||||
|| property.isAnnotationPresent(MapKey.class)
|
|| property.isAnnotationPresent(MapKey.class)
|
||||||
|| property.isAnnotationPresent(MapKeyType.class);
|
|| property.isAnnotationPresent(MapKeyType.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isToManyAssociationWithinEmbeddableCollection(PropertyHolder propertyHolder) {
|
private static boolean isToManyAssociationWithinEmbeddableCollection(PropertyHolder propertyHolder) {
|
||||||
if(propertyHolder instanceof ComponentPropertyHolder) {
|
if ( propertyHolder instanceof ComponentPropertyHolder ) {
|
||||||
ComponentPropertyHolder componentPropertyHolder = (ComponentPropertyHolder) propertyHolder;
|
ComponentPropertyHolder componentPropertyHolder = (ComponentPropertyHolder) propertyHolder;
|
||||||
return componentPropertyHolder.isWithinElementCollection();
|
return componentPropertyHolder.isWithinElementCollection();
|
||||||
}
|
}
|
||||||
return false;
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static AnnotatedColumn[] elementColumns(
|
private static AnnotatedColumn[] elementColumns(
|
||||||
|
@ -539,8 +540,8 @@ public abstract class CollectionBinder {
|
||||||
CollectionBinder collectionBinder,
|
CollectionBinder collectionBinder,
|
||||||
Comment comment) {
|
Comment comment) {
|
||||||
|
|
||||||
final jakarta.persistence.Column[] keyColumns = property.isAnnotationPresent(MapKeyColumn.class)
|
final jakarta.persistence.Column[] keyColumns = property.isAnnotationPresent( MapKeyColumn.class )
|
||||||
? new jakarta.persistence.Column[] { new MapKeyColumnDelegator( property.getAnnotation(MapKeyColumn.class) ) }
|
? new jakarta.persistence.Column[] { new MapKeyColumnDelegator( property.getAnnotation( MapKeyColumn.class ) ) }
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
final AnnotatedColumn[] mapColumns = buildColumnsFromAnnotations(
|
final AnnotatedColumn[] mapColumns = buildColumnsFromAnnotations(
|
||||||
|
@ -557,7 +558,7 @@ public abstract class CollectionBinder {
|
||||||
|
|
||||||
if ( property.isAnnotationPresent( MapKeyJoinColumns.class ) ) {
|
if ( property.isAnnotationPresent( MapKeyJoinColumns.class ) ) {
|
||||||
final MapKeyJoinColumn[] mapKeyJoinColumns = property.getAnnotation( MapKeyJoinColumns.class ).value();
|
final MapKeyJoinColumn[] mapKeyJoinColumns = property.getAnnotation( MapKeyJoinColumns.class ).value();
|
||||||
JoinColumn[] joinKeyColumns = new JoinColumn[mapKeyJoinColumns.length];
|
final JoinColumn[] joinKeyColumns = new JoinColumn[mapKeyJoinColumns.length];
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for ( MapKeyJoinColumn joinColumn : mapKeyJoinColumns ) {
|
for ( MapKeyJoinColumn joinColumn : mapKeyJoinColumns ) {
|
||||||
joinKeyColumns[index] = new MapKeyJoinColumnDelegator( joinColumn );
|
joinKeyColumns[index] = new MapKeyJoinColumnDelegator( joinColumn );
|
||||||
|
@ -570,13 +571,7 @@ public abstract class CollectionBinder {
|
||||||
return joinKeyColumns;
|
return joinKeyColumns;
|
||||||
}
|
}
|
||||||
else if ( property.isAnnotationPresent( MapKeyJoinColumn.class ) ) {
|
else if ( property.isAnnotationPresent( MapKeyJoinColumn.class ) ) {
|
||||||
return new JoinColumn[] {
|
return new JoinColumn[] { new MapKeyJoinColumnDelegator( property.getAnnotation( MapKeyJoinColumn.class ) ) };
|
||||||
new MapKeyJoinColumnDelegator(
|
|
||||||
property.getAnnotation(
|
|
||||||
MapKeyJoinColumn.class
|
|
||||||
)
|
|
||||||
)
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -648,7 +643,7 @@ public abstract class CollectionBinder {
|
||||||
annJoins = null;
|
annJoins = null;
|
||||||
annInverseJoins = null;
|
annInverseJoins = null;
|
||||||
}
|
}
|
||||||
AnnotatedJoinColumn[] joinColumns = buildJoinTableJoinColumns(
|
final AnnotatedJoinColumn[] joinColumns = buildJoinTableJoinColumns(
|
||||||
annJoins,
|
annJoins,
|
||||||
entityBinder.getSecondaryTables(),
|
entityBinder.getSecondaryTables(),
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
|
@ -656,7 +651,7 @@ public abstract class CollectionBinder {
|
||||||
mappedBy,
|
mappedBy,
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
AnnotatedJoinColumn[] inverseJoinColumns = buildJoinTableJoinColumns(
|
final AnnotatedJoinColumn[] inverseJoinColumns = buildJoinTableJoinColumns(
|
||||||
annInverseJoins,
|
annInverseJoins,
|
||||||
entityBinder.getSecondaryTables(),
|
entityBinder.getSecondaryTables(),
|
||||||
propertyHolder,
|
propertyHolder,
|
||||||
|
@ -1537,7 +1532,7 @@ public abstract class CollectionBinder {
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
PersistentClass persistentClass = persistentClasses.get( elementType.getName() );
|
PersistentClass persistentClass = persistentClasses.get( elementType.getName() );
|
||||||
boolean reversePropertyInJoin = false;
|
boolean reversePropertyInJoin = false;
|
||||||
if ( persistentClass != null && isNotEmpty( mappedBy ) ) {
|
if ( persistentClass != null && hasMappedBy() ) {
|
||||||
try {
|
try {
|
||||||
reversePropertyInJoin =
|
reversePropertyInJoin =
|
||||||
0 != persistentClass.getJoinNumber( persistentClass.getRecursiveProperty( mappedBy ) );
|
0 != persistentClass.getJoinNumber( persistentClass.getRecursiveProperty( mappedBy ) );
|
||||||
|
@ -1551,11 +1546,11 @@ public abstract class CollectionBinder {
|
||||||
if ( persistentClass != null
|
if ( persistentClass != null
|
||||||
&& !reversePropertyInJoin
|
&& !reversePropertyInJoin
|
||||||
&& oneToMany
|
&& oneToMany
|
||||||
&& !this.isExplicitAssociationTable
|
&& !isExplicitAssociationTable
|
||||||
&& ( joinColumns[0].isImplicit() && !isEmptyAnnotationValue( this.mappedBy ) //implicit @JoinColumn
|
&& ( joinColumns[0].isImplicit() && hasMappedBy() //implicit @JoinColumn
|
||||||
|| !fkJoinColumns[0].isImplicit() ) //this is an explicit @JoinColumn
|
|| !fkJoinColumns[0].isImplicit() ) //this is an explicit @JoinColumn
|
||||||
) {
|
) {
|
||||||
//this is a Foreign key
|
//this is a foreign key
|
||||||
bindOneToManySecondPass(
|
bindOneToManySecondPass(
|
||||||
getCollection(),
|
getCollection(),
|
||||||
persistentClasses,
|
persistentClasses,
|
||||||
|
@ -1590,6 +1585,10 @@ public abstract class CollectionBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean hasMappedBy() {
|
||||||
|
return isNotEmpty( mappedBy );
|
||||||
|
}
|
||||||
|
|
||||||
protected void bindOneToManySecondPass(
|
protected void bindOneToManySecondPass(
|
||||||
Collection collection,
|
Collection collection,
|
||||||
Map<String, PersistentClass> persistentClasses,
|
Map<String, PersistentClass> persistentClasses,
|
||||||
|
@ -1608,16 +1607,16 @@ public abstract class CollectionBinder {
|
||||||
"CollectionSecondPass for oneToMany should not be called with null mappings"
|
"CollectionSecondPass for oneToMany should not be called with null mappings"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
org.hibernate.mapping.OneToMany oneToMany =
|
final org.hibernate.mapping.OneToMany oneToMany =
|
||||||
new org.hibernate.mapping.OneToMany( buildingContext, collection.getOwner() );
|
new org.hibernate.mapping.OneToMany( buildingContext, collection.getOwner() );
|
||||||
collection.setElement( oneToMany );
|
collection.setElement( oneToMany );
|
||||||
oneToMany.setReferencedEntityName( collectionType.getName() );
|
oneToMany.setReferencedEntityName( collectionType.getName() );
|
||||||
oneToMany.setNotFoundAction( notFoundAction );
|
oneToMany.setNotFoundAction( notFoundAction );
|
||||||
|
|
||||||
String assocClass = oneToMany.getReferencedEntityName();
|
final String assocClass = oneToMany.getReferencedEntityName();
|
||||||
PersistentClass associatedClass = persistentClasses.get( assocClass );
|
final PersistentClass associatedClass = persistentClasses.get( assocClass );
|
||||||
handleJpaOrderBy( collection, associatedClass );
|
handleJpaOrderBy( collection, associatedClass );
|
||||||
Map<String, Join> joins = buildingContext.getMetadataCollector().getJoins( assocClass );
|
final Map<String, Join> joins = buildingContext.getMetadataCollector().getJoins( assocClass );
|
||||||
if ( associatedClass == null ) {
|
if ( associatedClass == null ) {
|
||||||
throw new MappingException(
|
throw new MappingException(
|
||||||
String.format("Association [%s] for entity [%s] references unmapped class [%s]",
|
String.format("Association [%s] for entity [%s] references unmapped class [%s]",
|
||||||
|
@ -1625,7 +1624,7 @@ public abstract class CollectionBinder {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
oneToMany.setAssociatedClass( associatedClass );
|
oneToMany.setAssociatedClass( associatedClass );
|
||||||
for (AnnotatedJoinColumn column : fkJoinColumns) {
|
for ( AnnotatedJoinColumn column : fkJoinColumns ) {
|
||||||
column.setPersistentClass( associatedClass, joins, inheritanceStatePerClass );
|
column.setPersistentClass( associatedClass, joins, inheritanceStatePerClass );
|
||||||
column.setJoins( joins );
|
column.setJoins( joins );
|
||||||
collection.setCollectionTable( column.getTable() );
|
collection.setCollectionTable( column.getTable() );
|
||||||
|
@ -1646,19 +1645,19 @@ public abstract class CollectionBinder {
|
||||||
buildingContext
|
buildingContext
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( !collection.isInverse()
|
if ( !collection.isInverse() && !collection.getKey().isNullable() ) {
|
||||||
&& !collection.getKey().isNullable() ) {
|
|
||||||
// for non-inverse one-to-many, with a not-null fk, add a backref!
|
// for non-inverse one-to-many, with a not-null fk, add a backref!
|
||||||
String entityName = oneToMany.getReferencedEntityName();
|
final String entityName = oneToMany.getReferencedEntityName();
|
||||||
PersistentClass referenced = buildingContext.getMetadataCollector().getEntityBinding( entityName );
|
final PersistentClass referenced = buildingContext.getMetadataCollector().getEntityBinding( entityName );
|
||||||
Backref prop = new Backref();
|
final Backref backref = new Backref();
|
||||||
prop.setName( '_' + fkJoinColumns[0].getPropertyName() + '_' + fkJoinColumns[0].getLogicalColumnName() + "Backref" );
|
AnnotatedJoinColumn fkColumn = fkJoinColumns[0];
|
||||||
prop.setUpdateable( false );
|
backref.setName( '_' + fkColumn.getPropertyName() + '_' + fkColumn.getLogicalColumnName() + "Backref" );
|
||||||
prop.setSelectable( false );
|
backref.setUpdateable( false );
|
||||||
prop.setCollectionRole( collection.getRole() );
|
backref.setSelectable( false );
|
||||||
prop.setEntityName( collection.getOwner().getEntityName() );
|
backref.setCollectionRole( collection.getRole() );
|
||||||
prop.setValue( collection.getKey() );
|
backref.setEntityName( collection.getOwner().getEntityName() );
|
||||||
referenced.addProperty( prop );
|
backref.setValue( collection.getKey() );
|
||||||
|
referenced.addProperty( backref );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1698,7 +1697,7 @@ public abstract class CollectionBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addFilter(boolean hasAssociationTable, Filter filter) {
|
private void addFilter(boolean hasAssociationTable, Filter filter) {
|
||||||
if (hasAssociationTable) {
|
if ( hasAssociationTable ) {
|
||||||
collection.addManyToManyFilter(
|
collection.addManyToManyFilter(
|
||||||
filter.name(),
|
filter.name(),
|
||||||
getCondition(filter),
|
getCondition(filter),
|
||||||
|
@ -1914,7 +1913,7 @@ public abstract class CollectionBinder {
|
||||||
return orderByFragment;
|
return orderByFragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static DependantValue buildCollectionKey(
|
private DependantValue buildCollectionKey(
|
||||||
Collection collValue,
|
Collection collValue,
|
||||||
AnnotatedJoinColumn[] joinColumns,
|
AnnotatedJoinColumn[] joinColumns,
|
||||||
boolean cascadeDeleteEnabled,
|
boolean cascadeDeleteEnabled,
|
||||||
|
@ -2034,18 +2033,18 @@ public abstract class CollectionBinder {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void overrideReferencedPropertyName(
|
private void overrideReferencedPropertyName(
|
||||||
Collection collValue,
|
Collection collValue,
|
||||||
AnnotatedJoinColumn[] joinColumns,
|
AnnotatedJoinColumn[] joinColumns,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
if ( joinColumns.length > 0 ) {
|
if ( joinColumns.length > 0 ) {
|
||||||
AnnotatedJoinColumn joinColumn = joinColumns[0];
|
AnnotatedJoinColumn joinColumn = joinColumns[0];
|
||||||
if (isNotEmpty( joinColumn.getMappedBy() )) {
|
if ( hasMappedBy() ) {
|
||||||
String entityName = joinColumn.getManyToManyOwnerSideEntityName() != null
|
String entityName = joinColumn.getManyToManyOwnerSideEntityName() != null
|
||||||
? "inverse__" + joinColumn.getManyToManyOwnerSideEntityName()
|
? "inverse__" + joinColumn.getManyToManyOwnerSideEntityName()
|
||||||
: joinColumn.getPropertyHolder().getEntityName();
|
: joinColumn.getPropertyHolder().getEntityName();
|
||||||
InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
||||||
String propRef = metadataCollector.getPropertyReferencedAssociation( entityName, joinColumn.getMappedBy() );
|
String propRef = metadataCollector.getPropertyReferencedAssociation( entityName, mappedBy );
|
||||||
if ( propRef != null ) {
|
if ( propRef != null ) {
|
||||||
collValue.setReferencedPropertyName( propRef );
|
collValue.setReferencedPropertyName( propRef );
|
||||||
metadataCollector.addPropertyReference( collValue.getOwnerEntityName(), propRef );
|
metadataCollector.addPropertyReference( collValue.getOwnerEntityName(), propRef );
|
||||||
|
@ -2090,7 +2089,7 @@ public abstract class CollectionBinder {
|
||||||
isManyToAny
|
isManyToAny
|
||||||
);
|
);
|
||||||
|
|
||||||
if ( !isEmptyAnnotationValue( joinColumns[0].getMappedBy() ) ) {
|
if ( hasMappedBy() ) {
|
||||||
handleUnownedManyToMany(
|
handleUnownedManyToMany(
|
||||||
collValue,
|
collValue,
|
||||||
joinColumns,
|
joinColumns,
|
||||||
|
@ -2161,7 +2160,7 @@ public abstract class CollectionBinder {
|
||||||
|
|
||||||
//FIXME: do optional = false
|
//FIXME: do optional = false
|
||||||
if ( isCollectionOfEntities ) {
|
if ( isCollectionOfEntities ) {
|
||||||
bindManytoManyInverseFk( collectionEntity, inverseJoinColumns, element, unique, buildingContext );
|
bindManyToManyInverseForeignKey( collectionEntity, inverseJoinColumns, element, unique, buildingContext );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2495,7 +2494,7 @@ public abstract class CollectionBinder {
|
||||||
|
|
||||||
Property otherSideProperty;
|
Property otherSideProperty;
|
||||||
try {
|
try {
|
||||||
otherSideProperty = collectionEntity.getRecursiveProperty( joinColumns[0].getMappedBy() );
|
otherSideProperty = collectionEntity.getRecursiveProperty( mappedBy );
|
||||||
}
|
}
|
||||||
catch (MappingException e) {
|
catch (MappingException e) {
|
||||||
throw new AnnotationException( "Association '" + safeCollectionRole() +
|
throw new AnnotationException( "Association '" + safeCollectionRole() +
|
||||||
|
@ -2633,7 +2632,7 @@ public abstract class CollectionBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindCollectionSecondPass(
|
private void bindCollectionSecondPass(
|
||||||
Collection collValue,
|
Collection collValue,
|
||||||
PersistentClass collectionEntity,
|
PersistentClass collectionEntity,
|
||||||
AnnotatedJoinColumn[] joinColumns,
|
AnnotatedJoinColumn[] joinColumns,
|
||||||
|
@ -2674,19 +2673,17 @@ public abstract class CollectionBinder {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* bind the inverse FK of a {@link ManyToMany}.
|
* Bind the inverse foreign key of a {@link ManyToMany}.
|
||||||
* If we are in a mappedBy case, read the columns from the associated
|
* If we are in a mappedBy case, read the columns from the associated
|
||||||
* collection element
|
* collection element. Otherwise, delegate to the usual algorithm.
|
||||||
* Otherwise delegates to the usual algorithm
|
|
||||||
*/
|
*/
|
||||||
public void bindManytoManyInverseFk(
|
public void bindManyToManyInverseForeignKey(
|
||||||
PersistentClass referencedEntity,
|
PersistentClass referencedEntity,
|
||||||
AnnotatedJoinColumn[] columns,
|
AnnotatedJoinColumn[] columns,
|
||||||
SimpleValue value,
|
SimpleValue value,
|
||||||
boolean unique,
|
boolean unique,
|
||||||
MetadataBuildingContext buildingContext) {
|
MetadataBuildingContext buildingContext) {
|
||||||
final String mappedBy = columns[0].getMappedBy();
|
if ( hasMappedBy() ) {
|
||||||
if ( isNotEmpty( mappedBy ) ) {
|
|
||||||
final Property property = referencedEntity.getRecursiveProperty( mappedBy );
|
final Property property = referencedEntity.getRecursiveProperty( mappedBy );
|
||||||
final List<Selectable> mappedByColumns = mappedByColumns( referencedEntity, property );
|
final List<Selectable> mappedByColumns = mappedByColumns( referencedEntity, property );
|
||||||
for ( Selectable selectable: mappedByColumns ) {
|
for ( Selectable selectable: mappedByColumns ) {
|
||||||
|
|
|
@ -806,23 +806,18 @@ public class EntityBinder {
|
||||||
MetadataBuildingContext context,
|
MetadataBuildingContext context,
|
||||||
InheritanceState inheritanceState,
|
InheritanceState inheritanceState,
|
||||||
EntityBinder entityBinder) {
|
EntityBinder entityBinder) {
|
||||||
final boolean isRoot = !inheritanceState.hasParents();
|
|
||||||
|
|
||||||
DiscriminatorColumn discAnn = clazzToProcess.getAnnotation( DiscriminatorColumn.class );
|
DiscriminatorColumn discAnn = clazzToProcess.getAnnotation( DiscriminatorColumn.class );
|
||||||
DiscriminatorType discriminatorType = discAnn != null ? discAnn.discriminatorType() : DiscriminatorType.STRING;
|
DiscriminatorType discriminatorType = discAnn != null ? discAnn.discriminatorType() : DiscriminatorType.STRING;
|
||||||
|
|
||||||
DiscriminatorFormula discFormulaAnn = getOverridableAnnotation( clazzToProcess, DiscriminatorFormula.class, context );
|
DiscriminatorFormula discFormulaAnn = getOverridableAnnotation( clazzToProcess, DiscriminatorFormula.class, context );
|
||||||
|
|
||||||
AnnotatedDiscriminatorColumn discriminatorColumn = null;
|
final boolean isRoot = !inheritanceState.hasParents();
|
||||||
if ( isRoot ) {
|
final AnnotatedDiscriminatorColumn discriminatorColumn = isRoot
|
||||||
discriminatorColumn = buildDiscriminatorColumn(
|
? buildDiscriminatorColumn( discriminatorType, discAnn, discFormulaAnn, context )
|
||||||
discriminatorType,
|
: null;
|
||||||
discAnn,
|
|
||||||
discFormulaAnn,
|
|
||||||
context
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if ( discAnn != null && !isRoot ) {
|
if ( discAnn != null && !isRoot ) {
|
||||||
|
//TODO: shouldn't this be an error?!
|
||||||
LOG.invalidDiscriminatorAnnotation( clazzToProcess.getName() );
|
LOG.invalidDiscriminatorAnnotation( clazzToProcess.getName() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1808,7 +1803,7 @@ public class EntityBinder {
|
||||||
private void bindJoinToPersistentClass(Join join, AnnotatedJoinColumn[] annotatedJoinColumns, MetadataBuildingContext buildingContext) {
|
private void bindJoinToPersistentClass(Join join, AnnotatedJoinColumn[] annotatedJoinColumns, MetadataBuildingContext buildingContext) {
|
||||||
DependantValue key = new DependantValue( buildingContext, join.getTable(), persistentClass.getIdentifier() );
|
DependantValue key = new DependantValue( buildingContext, join.getTable(), persistentClass.getIdentifier() );
|
||||||
join.setKey( key );
|
join.setKey( key );
|
||||||
setFKNameIfDefined( join );
|
setForeignKeyNameIfDefined( join );
|
||||||
key.setCascadeDeleteEnabled( false );
|
key.setCascadeDeleteEnabled( false );
|
||||||
TableBinder.bindForeignKey( persistentClass, null, annotatedJoinColumns, key, false, buildingContext );
|
TableBinder.bindForeignKey( persistentClass, null, annotatedJoinColumns, key, false, buildingContext );
|
||||||
key.sortProperties();
|
key.sortProperties();
|
||||||
|
@ -1817,7 +1812,7 @@ public class EntityBinder {
|
||||||
persistentClass.addJoin( join );
|
persistentClass.addJoin( join );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFKNameIfDefined(Join join) {
|
private void setForeignKeyNameIfDefined(Join join) {
|
||||||
// just awful..
|
// just awful..
|
||||||
org.hibernate.annotations.Table matchingTable = findMatchingComplementaryTableAnnotation( join );
|
org.hibernate.annotations.Table matchingTable = findMatchingComplementaryTableAnnotation( join );
|
||||||
final SimpleValue key = (SimpleValue) join.getKey();
|
final SimpleValue key = (SimpleValue) join.getKey();
|
||||||
|
|
|
@ -372,7 +372,7 @@ public class MapBinder extends CollectionBinder {
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isIndexOfEntities ) {
|
if ( isIndexOfEntities ) {
|
||||||
bindManytoManyInverseFk(
|
bindManyToManyInverseForeignKey(
|
||||||
collectionEntity,
|
collectionEntity,
|
||||||
mapKeyManyToManyColumns,
|
mapKeyManyToManyColumns,
|
||||||
element,
|
element,
|
||||||
|
|
|
@ -535,6 +535,10 @@ public class PropertyBinder {
|
||||||
this.isId = id;
|
this.isId = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isId() {
|
||||||
|
return isId;
|
||||||
|
}
|
||||||
|
|
||||||
public void setInheritanceStatePerClass(Map<XClass, InheritanceState> inheritanceStatePerClass) {
|
public void setInheritanceStatePerClass(Map<XClass, InheritanceState> inheritanceStatePerClass) {
|
||||||
this.inheritanceStatePerClass = inheritanceStatePerClass;
|
this.inheritanceStatePerClass = inheritanceStatePerClass;
|
||||||
}
|
}
|
||||||
|
|
|
@ -547,11 +547,10 @@ public class TableBinder {
|
||||||
associatedClass = holder == null ? null : holder.getPersistentClass();
|
associatedClass = holder == null ? null : holder.getPersistentClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
final String mappedByProperty = columns[0].getMappedBy();
|
if ( columns[0].hasMappedBy() ) {
|
||||||
if ( isNotEmpty( mappedByProperty ) ) {
|
|
||||||
// use the columns of the property referenced by mappedBy
|
// use the columns of the property referenced by mappedBy
|
||||||
// copy them and link the copy to the actual value
|
// copy them and link the copy to the actual value
|
||||||
bindUnownedAssociation( columns, value, associatedClass, mappedByProperty );
|
bindUnownedAssociation( columns, value, associatedClass, columns[0].getMappedBy() );
|
||||||
}
|
}
|
||||||
else if ( columns[0].isImplicit() ) {
|
else if ( columns[0].isImplicit() ) {
|
||||||
// if columns are implicit, then create the columns based
|
// if columns are implicit, then create the columns based
|
||||||
|
@ -575,20 +574,20 @@ public class TableBinder {
|
||||||
PersistentClass associatedClass) {
|
PersistentClass associatedClass) {
|
||||||
switch ( checkReferencedColumnsType( columns, referencedEntity, buildingContext ) ) {
|
switch ( checkReferencedColumnsType( columns, referencedEntity, buildingContext ) ) {
|
||||||
case NON_PK_REFERENCE: {
|
case NON_PK_REFERENCE: {
|
||||||
bindNonPkReference( referencedEntity, columns, value );
|
bindNonPrimaryKeyReference( referencedEntity, columns, value );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case NO_REFERENCE: {
|
case NO_REFERENCE: {
|
||||||
bindImplicitPkReference( referencedEntity, columns, value, associatedClass );
|
bindImplicitPrimaryKeyReference( referencedEntity, columns, value, associatedClass );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
bindPkReference( referencedEntity, columns, value, associatedClass, buildingContext );
|
bindPrimaryKeyReference( referencedEntity, columns, value, associatedClass, buildingContext );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindImplicitPkReference(
|
private static void bindImplicitPrimaryKeyReference(
|
||||||
PersistentClass referencedEntity,
|
PersistentClass referencedEntity,
|
||||||
AnnotatedJoinColumn[] columns,
|
AnnotatedJoinColumn[] columns,
|
||||||
SimpleValue value,
|
SimpleValue value,
|
||||||
|
@ -613,7 +612,7 @@ public class TableBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindPkReference(
|
private static void bindPrimaryKeyReference(
|
||||||
PersistentClass referencedEntity,
|
PersistentClass referencedEntity,
|
||||||
AnnotatedJoinColumn[] columns,
|
AnnotatedJoinColumn[] columns,
|
||||||
SimpleValue value,
|
SimpleValue value,
|
||||||
|
@ -663,7 +662,7 @@ public class TableBinder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void bindNonPkReference(
|
private static void bindNonPrimaryKeyReference(
|
||||||
PersistentClass referencedEntity,
|
PersistentClass referencedEntity,
|
||||||
AnnotatedJoinColumn[] columns,
|
AnnotatedJoinColumn[] columns,
|
||||||
SimpleValue value) {
|
SimpleValue value) {
|
||||||
|
@ -680,7 +679,6 @@ public class TableBinder {
|
||||||
else {
|
else {
|
||||||
throw new AnnotationException( "The '@JoinColumn' for a secondary table must reference the primary key" );
|
throw new AnnotationException( "The '@JoinColumn' for a secondary table must reference the primary key" );
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new AssertionFailure( "Property ref to an unexpected Value type: " + value.getClass().getName() );
|
throw new AssertionFailure( "Property ref to an unexpected Value type: " + value.getClass().getName() );
|
||||||
|
|
|
@ -546,7 +546,7 @@ public final class StringHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isNotEmpty(String string) {
|
public static boolean isNotEmpty(String string) {
|
||||||
return string != null && string.length() > 0;
|
return string != null && !string.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isEmpty(String string) {
|
public static boolean isEmpty(String string) {
|
||||||
|
|
|
@ -57,7 +57,7 @@ public class AndFormulaTest {
|
||||||
fail( "Expecting failure from invalid mapping" );
|
fail( "Expecting failure from invalid mapping" );
|
||||||
}
|
}
|
||||||
catch (CannotForceNonNullableException e) {
|
catch (CannotForceNonNullableException e) {
|
||||||
assertThat( e.getMessage(), startsWith( "Identifier property [" ) );
|
assertThat( e.getMessage(), startsWith( "Identifier property " ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,6 @@ import org.hibernate.testing.OnExpectedFailure;
|
||||||
import org.hibernate.testing.OnFailure;
|
import org.hibernate.testing.OnFailure;
|
||||||
import org.hibernate.testing.orm.UnclosedFixtureResourcesLogging;
|
import org.hibernate.testing.orm.UnclosedFixtureResourcesLogging;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metadata about various types of callback methods on a given test class.
|
* Metadata about various types of callback methods on a given test class.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue