further cleanups to the Binder code

This commit is contained in:
Gavin King 2022-10-28 12:22:02 +02:00
parent f4687ac048
commit 86906013c2
17 changed files with 586 additions and 675 deletions

View File

@ -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) {

View File

@ -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 );
} }

View File

@ -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) {

View File

@ -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 );

View File

@ -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";
} }

View File

@ -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
*/ */

View File

@ -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;
} }
} }

View File

@ -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;
} }
} }

View File

@ -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 ) {

View File

@ -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 ) {

View File

@ -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();

View File

@ -372,7 +372,7 @@ public class MapBinder extends CollectionBinder {
} }
if ( isIndexOfEntities ) { if ( isIndexOfEntities ) {
bindManytoManyInverseFk( bindManyToManyInverseForeignKey(
collectionEntity, collectionEntity,
mapKeyManyToManyColumns, mapKeyManyToManyColumns,
element, element,

View File

@ -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;
} }

View File

@ -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() );

View File

@ -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) {

View File

@ -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 " ) );
} }
} }

View File

@ -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.
* *