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) {
final Identifier identifier = normalizeIdentifierQuoting( identifierText );
if ( identifier == null ) {
return null;
}
return identifier.render( database().getDialect() );
return identifier == null ? null : identifier.render( database().getDialect() );
}
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.getPath;
import static org.hibernate.cfg.BinderHelper.getRelativePath;
import static org.hibernate.internal.util.StringHelper.isEmpty;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
/**
@ -310,7 +311,7 @@ public class AnnotatedColumn {
}
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) {
@ -655,7 +656,7 @@ public class AnnotatedColumn {
}
public static AnnotatedColumn[] buildColumnsOrFormulaFromAnnotation(
jakarta.persistence.Column[] columnAnns,
jakarta.persistence.Column[] columns,
org.hibernate.annotations.Formula formulaAnn,
Comment comment,
Nullability nullability,
@ -675,7 +676,7 @@ public class AnnotatedColumn {
return new AnnotatedColumn[] { formulaColumn };
}
else {
jakarta.persistence.Column[] actualCols = overrideColumns( columnAnns, propertyHolder, inferredData);
jakarta.persistence.Column[] actualCols = overrideColumns( columns, propertyHolder, inferredData);
if ( actualCols == null ) {
return buildImplicitColumn(
inferredData,
@ -702,7 +703,7 @@ public class AnnotatedColumn {
}
private static jakarta.persistence.Column[] overrideColumns(
jakarta.persistence.Column[] columnAnns,
jakarta.persistence.Column[] columns,
PropertyHolder propertyHolder,
PropertyData inferredData ) {
final jakarta.persistence.Column[] overriddenCols = propertyHolder.getOverriddenColumn(
@ -710,11 +711,11 @@ public class AnnotatedColumn {
);
if ( overriddenCols != null ) {
//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
// PersistentClass.validate() gets called first and produces a worse message
throw new AnnotationException( "Property '" + getPath( propertyHolder, inferredData )
+ "' specifies " + columnAnns.length
+ "' specifies " + columns.length
+ " '@AttributeOverride's but the overridden property has " + overriddenCols.length
+ " columns (every column must have exactly one '@AttributeOverride')" );
}
@ -722,7 +723,7 @@ public class AnnotatedColumn {
return overriddenCols.length == 0 ? null : overriddenCols;
}
else {
return columnAnns;
return columns;
}
}
@ -741,7 +742,7 @@ public class AnnotatedColumn {
final Database database = context.getMetadataCollector().getDatabase();
final String sqlType = column.columnDefinition().isEmpty() ? null
: 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();
// final Identifier logicalName = database.getJdbcEnvironment()
// .getIdentifierHelper()
@ -813,7 +814,7 @@ public class AnnotatedColumn {
final String columnName = column.name() != null && column.name().isEmpty() ? null
: database.getJdbcEnvironment().getIdentifierHelper().toIdentifier( column.name() ).render();
// 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
: columnName;
}
@ -823,16 +824,14 @@ public class AnnotatedColumn {
if ( xProperty != null ) {
ColumnDefault columnDefault = getOverridableAnnotation( xProperty, ColumnDefault.class, context );
if ( columnDefault != null ) {
if (length!=1) {
if ( length!=1 ) {
throw new MappingException("@ColumnDefault may only be applied to single-column mappings");
}
setDefaultValue( columnDefault.value() );
}
}
else {
LOG.trace(
"Could not perform @ColumnDefault lookup as 'PropertyData' did not give access to XProperty"
);
LOG.trace("Could not perform @ColumnDefault lookup as 'PropertyData' did not give access to XProperty");
}
}
@ -848,9 +847,7 @@ public class AnnotatedColumn {
}
}
else {
LOG.trace(
"Could not perform @GeneratedColumn lookup as 'PropertyData' did not give access to XProperty"
);
LOG.trace("Could not perform @GeneratedColumn lookup as 'PropertyData' did not give access to XProperty");
}
}
@ -866,9 +863,7 @@ public class AnnotatedColumn {
}
}
else {
LOG.trace(
"Could not perform @Check lookup as 'PropertyData' did not give access to XProperty"
);
LOG.trace("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) {
if ( annotation != null ) {
if ( StringHelper.isEmpty( annotation.forColumn() )
if ( isEmpty( annotation.forColumn() )
// "" is the default value for annotations
|| annotation.forColumn().equals( logicalColumnName != null ? logicalColumnName : "" ) ) {
readExpression = StringHelper.nullIfEmpty( annotation.read() );
@ -947,7 +942,7 @@ public class AnnotatedColumn {
column.setJoins(secondaryTables);
column.setBuildingContext(context);
// property name + suffix is an "explicit" column name
boolean implicit = StringHelper.isEmpty( suffixForDefaultColumnName );
boolean implicit = isEmpty( suffixForDefaultColumnName );
if ( !implicit ) {
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.getRelativePath;
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
@ -90,46 +94,13 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
this.mappedBy = mappedBy;
}
//Due to @AnnotationOverride overriding rules, I don't want the constructor to be public
private AnnotatedJoinColumn() {
setMappedBy("");
public boolean hasMappedBy() {
return isNotEmpty( mappedBy );
}
//Due to @AnnotationOverride overriding rules, I don't want the constructor to be public
//TODO get rid of it and use setters
private AnnotatedJoinColumn(
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;
private AnnotatedJoinColumn() {
setMappedBy("");
}
public String getReferencedColumn() {
@ -137,44 +108,55 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
}
public static AnnotatedJoinColumn[] buildJoinColumnsOrFormulas(
JoinColumnOrFormula[] anns,
JoinColumnOrFormula[] joinColumnOrFormulas,
String mappedBy,
Map<String, Join> joins,
PropertyHolder propertyHolder,
String propertyName,
MetadataBuildingContext buildingContext) {
AnnotatedJoinColumn[] joinColumns = new AnnotatedJoinColumn[anns.length];
for (int i = 0; i < anns.length; i++) {
JoinColumnOrFormula join = anns[i];
JoinFormula formula = join.formula();
final AnnotatedJoinColumn[] joinColumns = new AnnotatedJoinColumn[joinColumnOrFormulas.length];
for (int i = 0; i < joinColumnOrFormulas.length; i++) {
JoinColumnOrFormula columnOrFormula = joinColumnOrFormulas[i];
JoinFormula formula = columnOrFormula.formula();
if ( formula.value() != null && !formula.value().isEmpty() ) {
joinColumns[i] = buildJoinFormula(
formula, mappedBy, joins, propertyHolder, propertyName, buildingContext
);
joinColumns[i] = buildJoinFormula( formula, joins, propertyHolder, propertyName, buildingContext );
}
else {
joinColumns[i] = buildJoinColumns(
new JoinColumn[] { join.column() }, null, mappedBy, joins, propertyHolder, propertyName, buildingContext
)[0];
joinColumns[i] = buildJoinColumn( mappedBy, joins, propertyHolder, propertyName, buildingContext, columnOrFormula );
}
}
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
*/
public static AnnotatedJoinColumn buildJoinFormula(
JoinFormula ann,
String mappedBy,
JoinFormula joinFormula,
Map<String, Join> joins,
PropertyHolder propertyHolder,
String propertyName,
MetadataBuildingContext buildingContext) {
AnnotatedJoinColumn formulaColumn = new AnnotatedJoinColumn();
formulaColumn.setFormula( ann.value() );
formulaColumn.setReferencedColumn(ann.referencedColumnName());
formulaColumn.setFormula( joinFormula.value() );
formulaColumn.setReferencedColumn(joinFormula.referencedColumnName());
formulaColumn.setBuildingContext( buildingContext );
formulaColumn.setPropertyHolder( propertyHolder );
formulaColumn.setJoins( joins );
@ -184,7 +166,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
}
public static AnnotatedJoinColumn[] buildJoinColumns(
JoinColumn[] anns,
JoinColumn[] joinColumns,
Comment comment,
String mappedBy,
Map<String, Join> joins,
@ -192,12 +174,19 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
String propertyName,
MetadataBuildingContext buildingContext) {
return buildJoinColumnsWithDefaultColumnSuffix(
anns, comment, mappedBy, joins, propertyHolder, propertyName, "", buildingContext
joinColumns,
comment,
mappedBy,
joins,
propertyHolder,
propertyName,
"",
buildingContext
);
}
public static AnnotatedJoinColumn[] buildJoinColumnsWithDefaultColumnSuffix(
JoinColumn[] anns,
JoinColumn[] joinColumns,
Comment comment,
String mappedBy,
Map<String, Join> joins,
@ -205,10 +194,8 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
String propertyName,
String suffixForDefaultColumnName,
MetadataBuildingContext buildingContext) {
JoinColumn[] actualColumns = propertyHolder.getOverriddenJoinColumn(
StringHelper.qualify( propertyHolder.getPath(), propertyName )
);
if ( actualColumns == null ) actualColumns = anns;
JoinColumn[] overriddes = propertyHolder.getOverriddenJoinColumn( qualify( propertyHolder.getPath(), propertyName ) );
JoinColumn[] actualColumns = overriddes == null ? joinColumns : overriddes;
if ( actualColumns == null || actualColumns.length == 0 ) {
return new AnnotatedJoinColumn[] {
buildJoinColumn(
@ -224,9 +211,8 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
};
}
else {
int size = actualColumns.length;
AnnotatedJoinColumn[] result = new AnnotatedJoinColumn[size];
for (int index = 0; index < size; index++) {
final AnnotatedJoinColumn[] result = new AnnotatedJoinColumn[actualColumns.length];
for (int index = 0; index < actualColumns.length; index++ ) {
result[index] = buildJoinColumn(
actualColumns[index],
comment,
@ -246,88 +232,84 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
* build join column for SecondaryTables
*/
private static AnnotatedJoinColumn buildJoinColumn(
JoinColumn ann,
JoinColumn joinColumn,
Comment comment,
String mappedBy, Map<String, Join> joins,
PropertyHolder propertyHolder,
String propertyName,
String suffixForDefaultColumnName,
MetadataBuildingContext buildingContext) {
if ( ann != null ) {
if ( !BinderHelper.isEmptyOrNullAnnotationValue( mappedBy ) ) {
if ( joinColumn != null ) {
if ( !isEmptyOrNullAnnotationValue( mappedBy ) ) {
throw new AnnotationException(
"Association '" + getRelativePath( propertyHolder, propertyName )
+ "' is 'mappedBy' a different entity and may not explicitly specify the '@JoinColumn'"
);
}
AnnotatedJoinColumn joinColumn = new AnnotatedJoinColumn();
joinColumn.setComment( comment != null ? comment.value() : null );
joinColumn.setBuildingContext( buildingContext );
joinColumn.setJoinAnnotation( ann, null );
if ( StringHelper.isEmpty( joinColumn.getLogicalColumnName() )
&& ! StringHelper.isEmpty( suffixForDefaultColumnName ) ) {
joinColumn.setLogicalColumnName( propertyName + suffixForDefaultColumnName );
AnnotatedJoinColumn column = new AnnotatedJoinColumn();
column.setComment( comment != null ? comment.value() : null );
column.setBuildingContext( buildingContext );
column.setJoinAnnotation( joinColumn, null );
if ( isEmpty( column.getLogicalColumnName() ) && isNotEmpty( suffixForDefaultColumnName ) ) {
column.setLogicalColumnName( propertyName + suffixForDefaultColumnName );
}
joinColumn.setJoins( joins );
joinColumn.setPropertyHolder( propertyHolder );
joinColumn.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
joinColumn.setImplicit( false );
joinColumn.bind();
return joinColumn;
column.setJoins( joins );
column.setPropertyHolder( propertyHolder );
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
column.setImplicit( false );
column.bind();
return column;
}
else {
AnnotatedJoinColumn joinColumn = new AnnotatedJoinColumn();
joinColumn.setMappedBy( mappedBy );
joinColumn.setJoins( joins );
joinColumn.setPropertyHolder( propertyHolder );
joinColumn.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
AnnotatedJoinColumn column = new AnnotatedJoinColumn();
column.setMappedBy( mappedBy );
column.setJoins( joins );
column.setPropertyHolder( propertyHolder );
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
// property name + suffix is an "explicit" column name
if ( !StringHelper.isEmpty( suffixForDefaultColumnName ) ) {
joinColumn.setLogicalColumnName( propertyName + suffixForDefaultColumnName );
joinColumn.setImplicit( false );
if ( isNotEmpty( suffixForDefaultColumnName ) ) {
column.setLogicalColumnName( propertyName + suffixForDefaultColumnName );
column.setImplicit( false );
}
else {
joinColumn.setImplicit( true );
column.setImplicit( true );
}
joinColumn.setBuildingContext( buildingContext );
joinColumn.bind();
return joinColumn;
column.setBuildingContext( buildingContext );
column.bind();
return column;
}
}
// TODO default name still useful in association table
public void setJoinAnnotation(JoinColumn annJoin, String defaultName) {
if ( annJoin == null ) {
public void setJoinAnnotation(JoinColumn joinColumn, String defaultName) {
if ( joinColumn == null ) {
setImplicit( true );
}
else {
setImplicit( false );
if ( !isEmptyAnnotationValue( annJoin.columnDefinition() ) ) {
setSqlType( getBuildingContext().getObjectNameNormalizer().applyGlobalQuoting( annJoin.columnDefinition() ) );
if ( !isEmptyAnnotationValue( joinColumn.columnDefinition() ) ) {
setSqlType( getBuildingContext().getObjectNameNormalizer().applyGlobalQuoting( joinColumn.columnDefinition() ) );
}
if ( !isEmptyAnnotationValue( annJoin.name() ) ) {
setLogicalColumnName( annJoin.name() );
if ( !isEmptyAnnotationValue( joinColumn.name() ) ) {
setLogicalColumnName( joinColumn.name() );
}
setNullable( annJoin.nullable() );
setUnique( annJoin.unique() );
setInsertable( annJoin.insertable() );
setUpdatable( annJoin.updatable() );
setReferencedColumn( annJoin.referencedColumnName() );
setNullable( joinColumn.nullable() );
setUnique( joinColumn.unique() );
setInsertable( joinColumn.insertable() );
setUpdatable( joinColumn.updatable() );
setReferencedColumn( joinColumn.referencedColumnName() );
if ( isEmptyAnnotationValue( annJoin.table() ) ) {
if ( isEmptyAnnotationValue( joinColumn.table() ) ) {
setExplicitTableName( "" );
}
else {
final Identifier logicalIdentifier = getBuildingContext().getMetadataCollector()
.getDatabase()
.toIdentifier( annJoin.table() );
final Database database = getBuildingContext().getMetadataCollector().getDatabase();
final Identifier logicalIdentifier = database.toIdentifier( joinColumn.table() );
final Identifier physicalIdentifier = getBuildingContext().getBuildingOptions()
.getPhysicalNamingStrategy()
.toPhysicalTableName( logicalIdentifier, getBuildingContext().getMetadataCollector().getDatabase().getJdbcEnvironment() );
setExplicitTableName(
physicalIdentifier.render( getBuildingContext().getMetadataCollector().getDatabase().getDialect() )
);
.toPhysicalTableName( logicalIdentifier, database.getJdbcEnvironment() );
setExplicitTableName( physicalIdentifier.render( database.getDialect() ) );
}
}
}
@ -336,73 +318,60 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
* Build JoinColumn for a JOINED hierarchy
*/
public static AnnotatedJoinColumn buildJoinColumn(
PrimaryKeyJoinColumn pkJoinAnn,
JoinColumn joinAnn,
PrimaryKeyJoinColumn primaryKeyJoinColumn,
JoinColumn joinColumn,
Value identifier,
Map<String, Join> joins,
PropertyHolder propertyHolder,
MetadataBuildingContext context) {
final String defaultName = context.getMetadataCollector().getLogicalColumnName(
final String defaultColumnName = context.getMetadataCollector().getLogicalColumnName(
identifier.getTable(),
identifier.getColumns().get(0).getQuotedName()
);
final ObjectNameNormalizer normalizer = context.getObjectNameNormalizer();
if ( pkJoinAnn != null || joinAnn != null ) {
String colName;
String columnDefinition;
String referencedColumnName;
if ( pkJoinAnn != null ) {
colName = pkJoinAnn.name();
columnDefinition = pkJoinAnn.columnDefinition();
referencedColumnName = pkJoinAnn.referencedColumnName();
if ( primaryKeyJoinColumn != null || joinColumn != null ) {
final String columnName;
final String columnDefinition;
final String referencedColumnName;
if ( primaryKeyJoinColumn != null ) {
columnName = primaryKeyJoinColumn.name();
columnDefinition = primaryKeyJoinColumn.columnDefinition();
referencedColumnName = primaryKeyJoinColumn.referencedColumnName();
}
else {
colName = joinAnn.name();
columnDefinition = joinAnn.columnDefinition();
referencedColumnName = joinAnn.referencedColumnName();
columnName = joinColumn.name();
columnDefinition = joinColumn.columnDefinition();
referencedColumnName = joinColumn.referencedColumnName();
}
return new AnnotatedJoinColumn(
columnDefinition.isEmpty()
? null
: normalizer.toDatabaseIdentifierText( columnDefinition ),
colName != null && colName.isEmpty()
? normalizer.normalizeIdentifierQuotingAsString( defaultName )
: normalizer.normalizeIdentifierQuotingAsString( colName ),
null,
false,
false,
true,
true,
referencedColumnName,
null,
joins,
propertyHolder,
null,
null,
false,
context
);
final String columnDef = columnDefinition.isEmpty() ? null
: normalizer.toDatabaseIdentifierText( columnDefinition );
final String logicalColumnName = columnName != null && columnName.isEmpty()
? normalizer.normalizeIdentifierQuotingAsString( defaultColumnName )
: normalizer.normalizeIdentifierQuotingAsString( columnName );
AnnotatedJoinColumn column = new AnnotatedJoinColumn();
column.setSqlType( columnDef );
column.setLogicalColumnName( logicalColumnName );
column.setReferencedColumn( referencedColumnName );
column.setPropertyHolder( propertyHolder );
column.setJoins( joins );
column.setBuildingContext( context );
column.setImplicit( false );
column.setNullable( false );
column.bind();
return column;
}
else {
return new AnnotatedJoinColumn(
null,
normalizer.normalizeIdentifierQuotingAsString( defaultName ),
null,
false,
false,
true,
true,
null,
null,
joins,
propertyHolder,
null,
null,
true,
context
);
AnnotatedJoinColumn column = new AnnotatedJoinColumn();
column.setLogicalColumnName( normalizer.normalizeIdentifierQuotingAsString( defaultColumnName ) );
column.setPropertyHolder( propertyHolder );
column.setJoins( joins );
column.setBuildingContext( context );
column.setImplicit( true );
column.setNullable( false );
column.bind();
return column;
}
}
@ -737,31 +706,25 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
@Override
protected void addColumnBinding(SimpleValue value) {
if ( StringHelper.isEmpty( mappedBy ) ) {
if ( isEmpty( mappedBy ) ) {
// 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
boolean isLogicalColumnQuoted = StringHelper.isQuoted( getLogicalColumnName() );
final ObjectNameNormalizer nameNormalizer = getBuildingContext().getObjectNameNormalizer();
final String logicalColumnName = nameNormalizer.normalizeIdentifierQuotingAsString( getLogicalColumnName() );
final String referencedColumn = nameNormalizer.normalizeIdentifierQuotingAsString( getReferencedColumn() );
final String unquotedLogColName = StringHelper.unquote( logicalColumnName );
final String unquotedRefColumn = StringHelper.unquote( referencedColumn );
String logicalCollectionColumnName = StringHelper.isNotEmpty( unquotedLogColName )
final String collectionColName = isNotEmpty( unquotedLogColName )
? unquotedLogColName
: getPropertyName() + '_' + unquotedRefColumn;
logicalCollectionColumnName = getBuildingContext().getMetadataCollector()
.getDatabase()
final InFlightMetadataCollector collector = getBuildingContext().getMetadataCollector();
final String logicalCollectionColumnName = collector.getDatabase()
.getJdbcEnvironment()
.getIdentifierHelper()
.toIdentifier( logicalCollectionColumnName, isLogicalColumnQuoted )
.toIdentifier( collectionColName, isLogicalColumnQuoted )
.render();
getBuildingContext().getMetadataCollector().addColumnNameBinding(
value.getTable(),
logicalCollectionColumnName,
getMappingColumn()
);
collector.addColumnNameBinding( value.getTable(), logicalCollectionColumnName, getMappingColumn() );
}
}
@ -802,7 +765,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
boolean explicitColumnReference = false;
for ( AnnotatedJoinColumn column : columns ) {
final String logicalReferencedColumnName = column.getReferencedColumn();
if ( StringHelper.isNotEmpty( logicalReferencedColumnName ) ) {
if ( isNotEmpty( logicalReferencedColumnName ) ) {
explicitColumnReference = true;
if ( !keyColumns.contains( column( context, table, logicalReferencedColumnName ) ) ) {
// we have a column which does not belong to the PK
@ -844,7 +807,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
if ( mappingColumn != null ) {
// columnDefinition can also be specified using @JoinColumn, hence we have to check
// whether it is set or not
if ( StringHelper.isEmpty( sqlType ) ) {
if ( isEmpty( sqlType ) ) {
sqlType = column.getSqlType();
mappingColumn.setSqlType( sqlType );
}
@ -862,46 +825,44 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
}
public static AnnotatedJoinColumn[] buildJoinTableJoinColumns(
JoinColumn[] annJoins,
JoinColumn[] joinColumns,
Map<String, Join> secondaryTables,
PropertyHolder propertyHolder,
String propertyName,
String mappedBy,
MetadataBuildingContext buildingContext) {
AnnotatedJoinColumn[] joinColumns;
if ( annJoins == null ) {
AnnotatedJoinColumn currentJoinColumn = new AnnotatedJoinColumn();
currentJoinColumn.setImplicit( true );
currentJoinColumn.setNullable( false ); //I break the spec, but it's for good
currentJoinColumn.setPropertyHolder( propertyHolder );
currentJoinColumn.setJoins( secondaryTables );
currentJoinColumn.setBuildingContext( buildingContext );
currentJoinColumn.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
currentJoinColumn.setMappedBy( mappedBy );
currentJoinColumn.bind();
joinColumns = new AnnotatedJoinColumn[] { currentJoinColumn };
if ( joinColumns == null ) {
final AnnotatedJoinColumn column = new AnnotatedJoinColumn();
column.setImplicit( true );
column.setNullable( false ); //I break the spec, but it's for good
column.setPropertyHolder( propertyHolder );
column.setJoins( secondaryTables );
column.setBuildingContext( buildingContext );
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
column.setMappedBy( mappedBy );
column.bind();
return new AnnotatedJoinColumn[] { column };
}
else {
joinColumns = new AnnotatedJoinColumn[annJoins.length];
JoinColumn annJoin;
int length = annJoins.length;
final AnnotatedJoinColumn[] columns = new AnnotatedJoinColumn[joinColumns.length];
int length = joinColumns.length;
for (int index = 0; index < length; index++) {
annJoin = annJoins[index];
AnnotatedJoinColumn currentJoinColumn = new AnnotatedJoinColumn();
currentJoinColumn.setImplicit( true );
currentJoinColumn.setPropertyHolder( propertyHolder );
currentJoinColumn.setJoins( secondaryTables );
currentJoinColumn.setBuildingContext( buildingContext );
currentJoinColumn.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
currentJoinColumn.setMappedBy( mappedBy );
currentJoinColumn.setJoinAnnotation( annJoin, propertyName );
currentJoinColumn.setNullable( false ); //I break the spec, but it's for good
final JoinColumn joinColumn = joinColumns[index];
final AnnotatedJoinColumn column = new AnnotatedJoinColumn();
column.setImplicit( true );
column.setPropertyHolder( propertyHolder );
column.setJoins( secondaryTables );
column.setBuildingContext( buildingContext );
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
column.setMappedBy( mappedBy );
column.setJoinAnnotation( joinColumn, propertyName );
column.setNullable( false ); //I break the spec, but it's for good
//done after the annotation to override it
currentJoinColumn.bind();
joinColumns[index] = currentJoinColumn;
column.bind();
columns[index] = column;
}
return columns;
}
return joinColumns;
}
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;
/**
* JSR 175 annotation binder which reads the annotations from classes, applies the
* principles of the EJB3 spec and produces the Hibernate configuration-time metamodel
* (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.
* Reads annotations from Java classes and produces the Hibernate configuration-time metamodel,
* that is, the objects defined in the package {@link org.hibernate.mapping}.
*
* @author Emmanuel Bernard
* @author Hardy Ferentschik
*/
@SuppressWarnings("deprecation")
public final class AnnotationBinder {
private static final CoreMessageLogger LOG = messageLogger( AnnotationBinder.class );
@ -1262,8 +1248,7 @@ public final class AnnotationBinder {
columnsBuilder,
columns,
returnedClass,
propertyBinder,
isId
propertyBinder
);
}
}
@ -1349,18 +1334,16 @@ public final class AnnotationBinder {
ColumnsBuilder columnsBuilder,
AnnotatedColumn[] columns,
XClass returnedClass,
PropertyBinder propertyBinder,
boolean isId) {
//define whether the type is a component or not
PropertyBinder propertyBinder) {
boolean isComponent = false;
//Overrides from @MapsId if needed
boolean isOverridden = false;
if ( isId || propertyHolder.isOrWithinEmbeddedId() || propertyHolder.isInIdClass() ) {
//the associated entity could be using an @IdClass making the overridden property a component
PropertyData overridingProperty = getPropertyOverriddenByMapperOrMapsId(
isId,
// overrides from @MapsId or @IdClass if needed
final boolean isComposite;
final boolean isOverridden;
final AnnotatedColumn[] actualColumns;
if ( propertyBinder.isId() || propertyHolder.isOrWithinEmbeddedId() || propertyHolder.isInIdClass() ) {
// the associated entity could be using an @IdClass making the overridden property a component
final PropertyData overridingProperty = getPropertyOverriddenByMapperOrMapsId(
propertyBinder.isId(),
propertyHolder,
property.getName(),
context
@ -1368,143 +1351,210 @@ public final class AnnotationBinder {
if ( overridingProperty != null ) {
isOverridden = true;
final InheritanceState state = inheritanceStatePerClass.get( overridingProperty.getClassOrElement() );
if ( state != null ) {
isComponent = state.hasIdClassOrEmbeddedId();
}
isComposite = state != null ? state.hasIdClassOrEmbeddedId() : isEmbedded( property, returnedClass );
//Get the new column
columns = columnsBuilder.overrideColumnFromMapperOrMapsIdProperty(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();
actualColumns = columnsBuilder.overrideColumnFromMapperOrMapsIdProperty( propertyBinder.isId() );
}
else {
referencedEntityName = null;
propertyName = null;
isOverridden = false;
isComposite = isEmbedded( property, returnedClass );
actualColumns = columns;
}
}
else {
isOverridden = false;
isComposite = isEmbedded( property, returnedClass );
actualColumns = columns;
}
propertyBinder = bindComponent(
inferredData,
final Class<? extends CompositeUserType<?>> compositeUserType = resolveCompositeUserType( inferredData, context );
if ( isComposite || compositeUserType != null ) {
propertyBinder = createCompositeBinder(
propertyHolder,
entityBinder.getPropertyAccessor(property),
inferredData,
entityBinder,
isIdentifierMapper,
context,
isComponentEmbedded,
isId,
context,
inheritanceStatePerClass,
referencedEntityName,
propertyName,
determineCustomInstantiator( property, returnedClass, context ),
compositeUserType,
isOverridden ? (AnnotatedJoinColumn[]) columns : null
property,
actualColumns,
returnedClass,
propertyBinder,
isOverridden,
compositeUserType
);
}
else {
//provide the basic property mapping
boolean optional = true;
boolean lazy = false;
if ( property.isAnnotationPresent( Basic.class ) ) {
Basic ann = property.getAnnotation( Basic.class );
optional = ann.optional();
lazy = ann.fetch() == FetchType.LAZY;
}
//implicit type will check basic types and Serializable classes
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();
createBasicBinder(
propertyHolder,
inferredData,
nullability,
context,
property,
actualColumns,
propertyBinder,
isOverridden
);
}
if ( isOverridden ) {
final PropertyData mapsIdProperty = getPropertyOverriddenByMapperOrMapsId(
isId, propertyHolder, property.getName(), context
handleGeneratorsForOverriddenId(
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
if ( !isOverridden ) {
processId(
propertyHolder,
inferredData,
(SimpleValue) propertyBinder.getValue(),
classGenerators,
isIdentifierMapper,
context
);
processId(
propertyHolder,
inferredData,
(SimpleValue) propertyBinder.getValue(),
classGenerators,
isIdentifierMapper,
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) {
@ -1759,9 +1809,11 @@ public final class AnnotationBinder {
}
private static Class<? extends CompositeUserType<?>> resolveCompositeUserType(
XProperty property,
XClass returnedClass,
PropertyData inferredData,
MetadataBuildingContext context) {
final XProperty property = inferredData.getProperty();
final XClass returnedClass = inferredData.getClassOrElement();
if ( property != null ) {
final CompositeType compositeType = property.getAnnotation( CompositeType.class );
if ( compositeType != null ) {
@ -1941,9 +1993,9 @@ public final class AnnotationBinder {
Class<? extends EmbeddableInstantiator> customInstantiatorImpl,
Class<? extends CompositeUserType<?>> compositeUserTypeClass,
AnnotatedJoinColumn[] columns) {
Component comp;
final Component component;
if ( referencedEntityName != null ) {
comp = createComponent(
component = createComponent(
propertyHolder,
inferredData,
isComponentEmbedded,
@ -1952,7 +2004,7 @@ public final class AnnotationBinder {
buildingContext
);
SecondPass sp = new CopyIdentifierComponentSecondPass(
comp,
component,
referencedEntityName,
propertyName,
columns,
@ -1961,7 +2013,7 @@ public final class AnnotationBinder {
buildingContext.getMetadataCollector().addSecondPass( sp );
}
else {
comp = fillComponent(
component = fillComponent(
propertyHolder,
inferredData,
propertyAccessor,
@ -1977,18 +2029,18 @@ public final class AnnotationBinder {
);
}
if ( isId ) {
comp.setKey( true );
component.setKey( true );
if ( propertyHolder.getPersistentClass().getIdentifier() != null ) {
throw new AnnotationException(
"Embeddable class '" + comp.getComponentClassName()
"Embeddable class '" + component.getComponentClassName()
+ "' may not have a property annotated '@Id' since it is used by '"
+ getPath( propertyHolder, inferredData )
+ "' as an '@EmbeddedId'"
);
}
if ( referencedEntityName == null && comp.getPropertySpan() == 0 ) {
if ( referencedEntityName == null && component.getPropertySpan() == 0 ) {
throw new AnnotationException(
"Embeddable class '" + comp.getComponentClassName()
"Embeddable class '" + component.getComponentClassName()
+ "' may not be used as an '@EmbeddedId' by '"
+ getPath( propertyHolder, inferredData )
+ "' because it has no properties"
@ -1996,9 +2048,9 @@ public final class AnnotationBinder {
}
}
PropertyBinder binder = new PropertyBinder();
binder.setDeclaringClass(inferredData.getDeclaringClass());
binder.setDeclaringClass( inferredData.getDeclaringClass() );
binder.setName( inferredData.getPropertyName() );
binder.setValue( comp );
binder.setValue( component );
binder.setProperty( inferredData.getProperty() );
binder.setAccessType( inferredData.getDefaultAccess() );
binder.setEmbedded( isComponentEmbedded );

View File

@ -163,6 +163,7 @@ public class BinderHelper {
//associated entity only used for more precise exception
PersistentClass associatedEntity,
Value value,
//true when we do the reverse side of a @ManyToMany
boolean inverse,
MetadataBuildingContext context) {
@ -173,7 +174,7 @@ public class BinderHelper {
final AnnotatedJoinColumn firstColumn = columns[0];
if ( !firstColumn.isImplicit()
// only necessary for owning side of association
&& isEmpty( firstColumn.getMappedBy() )
&& !firstColumn.hasMappedBy()
// not necessary for a primary key reference
&& checkReferencedColumnsType( columns, ownerEntity, context ) == NON_PK_REFERENCE ) {
@ -301,7 +302,7 @@ public class BinderHelper {
String syntheticPropertyName =
"_" + associatedClass.getEntityName().replace('.', '_') +
"_" + propertyName.replace('.', '_');
if (inverse) {
if ( inverse ) {
// Use a different name for inverse synthetic properties to avoid duplicate properties for self-referencing models
syntheticPropertyName += "_inverse";
}

View File

@ -9,10 +9,10 @@ package org.hibernate.cfg;
import org.hibernate.AnnotationException;
/**
* Indicates an internal attempt to mark a column as non-nullable (because its part
* of a PK, etc) but we cannot force that column to be non-nullable.
* <p/>
* Typically this indicates that the "column" is actually a formula.
* Indicates an internal attempt to mark a column as non-nullable
* (because it's part of a primary key, for example) when we cannot
* force that column to be non-nullable. This usually indicates that
* the "column" is actually a formula.
*
* @author Steve Ebersole
*/

View File

@ -79,7 +79,7 @@ class ColumnsBuilder {
public ColumnsBuilder extractMetadata() {
columns = null;
joinColumns = buildExplicitJoinColumns(property, inferredData);
joinColumns = buildExplicitJoinColumns( property, inferredData );
Comment comment = property.getAnnotation(Comment.class);
@ -164,7 +164,7 @@ class ColumnsBuilder {
return this;
}
AnnotatedJoinColumn[] buildDefaultJoinColumnsForXToOne(XProperty property, PropertyData inferredData) {
private AnnotatedJoinColumn[] buildDefaultJoinColumnsForXToOne(XProperty property, PropertyData inferredData) {
AnnotatedJoinColumn[] joinColumns;
JoinTable joinTableAnn = propertyHolder.getJoinTable( property );
Comment comment = property.getAnnotation(Comment.class);
@ -201,23 +201,10 @@ class ColumnsBuilder {
return joinColumns;
}
AnnotatedJoinColumn[] buildExplicitJoinColumns(XProperty property, PropertyData inferredData) {
//process @JoinColumn(s) before @Column(s) 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" );
}
}
private AnnotatedJoinColumn[] buildExplicitJoinColumns(XProperty property, PropertyData inferredData) {
// process @JoinColumns before @Columns to handle collection of entities properly
final JoinColumn[] joinColumnAnnotations = getJoinColumnAnnotations(property, inferredData);
if ( joinColumnAnnotations != null ) {
return AnnotatedJoinColumn.buildJoinColumns(
joinColumnAnnotations,
@ -230,24 +217,8 @@ class ColumnsBuilder {
);
}
JoinColumnOrFormula[] 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) {
final JoinColumnOrFormula[] joinColumnOrFormulaAnnotations = joinColumnOrFormulaAnnotations( property, inferredData );
if ( joinColumnOrFormulaAnnotations != null ) {
return AnnotatedJoinColumn.buildJoinColumnsOrFormulas(
joinColumnOrFormulaAnnotations,
null,
@ -258,12 +229,11 @@ class ColumnsBuilder {
);
}
if (property.isAnnotationPresent( JoinFormula.class)) {
JoinFormula ann = getOverridableAnnotation( property, JoinFormula.class, buildingContext );
AnnotatedJoinColumn[] annotatedJoinColumns = new AnnotatedJoinColumn[1];
if ( property.isAnnotationPresent( JoinFormula.class) ) {
final JoinFormula joinFormula = getOverridableAnnotation( property, JoinFormula.class, buildingContext );
final AnnotatedJoinColumn[] annotatedJoinColumns = new AnnotatedJoinColumn[1];
annotatedJoinColumns[0] = AnnotatedJoinColumn.buildJoinFormula(
ann,
null,
joinFormula,
entityBinder.getSecondaryTables(),
propertyHolder,
inferredData.getPropertyName(),
@ -275,29 +245,57 @@ class ColumnsBuilder {
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[] result = columns;
final PropertyData overridingProperty = getPropertyOverriddenByMapperOrMapsId(
isId,
propertyHolder,
property.getName(),
buildingContext
);
if ( overridingProperty != null ) {
result = buildExcplicitOrDefaultJoinColumn( overridingProperty );
}
return result;
return overridingProperty != null ? buildExplicitOrDefaultJoinColumn( overridingProperty ) : columns;
}
/**
* useful to override a column either by @MapsId or by @IdClass
*/
AnnotatedColumn[] buildExcplicitOrDefaultJoinColumn(PropertyData overridingProperty) {
AnnotatedColumn[] result;
result = buildExplicitJoinColumns( overridingProperty.getProperty(), overridingProperty );
if (result == null) {
result = buildDefaultJoinColumnsForXToOne( overridingProperty.getProperty(), overridingProperty);
}
return result;
private AnnotatedColumn[] buildExplicitOrDefaultJoinColumn(PropertyData overridingProperty) {
final AnnotatedColumn[] columns = buildExplicitJoinColumns( overridingProperty.getProperty(), overridingProperty );
return columns == null ? buildDefaultJoinColumnsForXToOne( overridingProperty.getProperty(), overridingProperty ) : columns;
}
}

View File

@ -22,38 +22,10 @@ import static org.hibernate.cfg.BinderHelper.isEmptyAnnotationValue;
public class IndexColumn extends AnnotatedColumn {
private int base;
// TODO move to a getter setter strategy for readability
public IndexColumn(
boolean isImplicit,
String sqlType,
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 IndexColumn() {
setLength( 0L );
setPrecision( 0 );
setScale( 0 );
}
public static IndexColumn fromAnnotations(
@ -64,9 +36,9 @@ public class IndexColumn extends AnnotatedColumn {
PropertyData inferredData,
Map<String, Join> secondaryTables,
MetadataBuildingContext context) {
final IndexColumn indexColumn;
final IndexColumn column;
if ( jpaAnnotation != null ) {
indexColumn = buildColumnFromAnnotation(
column = buildColumnFromAnnotation(
jpaAnnotation,
propertyHolder,
inferredData,
@ -75,39 +47,28 @@ public class IndexColumn extends AnnotatedColumn {
);
}
else if ( hibAnnotation != null ) {
indexColumn = buildColumnFromAnnotation(
column = buildColumnFromAnnotation(
hibAnnotation,
propertyHolder,
inferredData,
context
);
indexColumn.setBase( hibAnnotation.base() );
column.setBase( hibAnnotation.base() );
}
else {
indexColumn = new IndexColumn(
true,
null,
0,
0,
0,
// Use the JPA default name...
inferredData.getPropertyName() + "_ORDER",
true,
false,
true,
true,
null,
null,
propertyHolder,
context
);
column = new IndexColumn();
column.setLogicalColumnName( inferredData.getPropertyName() + "_ORDER" ); //JPA default name
column.setImplicit( true );
column.setBuildingContext( context );
column.setPropertyHolder( propertyHolder );
column.bind();
}
if ( indexBaseAnnotation != null ) {
indexColumn.setBase( indexBaseAnnotation.value() );
column.setBase( indexBaseAnnotation.value() );
}
return indexColumn;
return column;
}
public int getBase() {
@ -134,54 +95,30 @@ public class IndexColumn extends AnnotatedColumn {
PropertyData inferredData,
Map<String, Join> secondaryTables,
MetadataBuildingContext buildingContext) {
final IndexColumn column;
if ( ann != null ) {
final String sqlType = isEmptyAnnotationValue( ann.columnDefinition() ) ? null : ann.columnDefinition();
final String name = isEmptyAnnotationValue( ann.name() ) ? inferredData.getPropertyName() + "_ORDER" : ann.name();
//TODO move it to a getter based system and remove the constructor
// The JPA OrderColumn annotation defines no table element...
// column = new IndexColumn(
// false, sqlType, 0, 0, 0, name, ann.nullable(),
// false, ann.insertable(), ann.updatable(), ann.table(),
// secondaryTables, propertyHolder, mappings
// );
column = new IndexColumn(
false,
sqlType,
0,
0,
0,
name,
ann.nullable(),
false,
ann.insertable(),
ann.updatable(),
//ann.table()
null,
secondaryTables,
propertyHolder,
buildingContext
);
final IndexColumn column = new IndexColumn();
column.setLogicalColumnName( name );
column.setSqlType( sqlType );
column.setNullable( ann.nullable() );
column.setJoins( secondaryTables );
column.setInsertable( ann.insertable() );
column.setUpdatable( ann.updatable() );
column.setBuildingContext( buildingContext );
column.setPropertyHolder( propertyHolder );
column.bind();
return column;
}
else {
column = new IndexColumn(
true,
null,
0,
0,
0,
null,
true,
false,
true,
true,
null,
null,
propertyHolder,
buildingContext
);
final IndexColumn column = new IndexColumn();
column.setImplicit( true );
column.setBuildingContext( buildingContext );
column.setPropertyHolder( propertyHolder );
column.bind();
return column;
}
return column;
}
/**
@ -198,47 +135,27 @@ public class IndexColumn extends AnnotatedColumn {
PropertyHolder propertyHolder,
PropertyData inferredData,
MetadataBuildingContext buildingContext) {
final IndexColumn column;
if ( ann != null ) {
final String sqlType = isEmptyAnnotationValue( ann.columnDefinition() ) ? null : ann.columnDefinition();
final String name = isEmptyAnnotationValue( ann.name() ) ? inferredData.getPropertyName() : ann.name();
//TODO move it to a getter based system and remove the constructor
column = new IndexColumn(
false,
sqlType,
0,
0,
0,
name,
ann.nullable(),
false,
true,
true,
null,
null,
propertyHolder,
buildingContext
);
final IndexColumn column = new IndexColumn();
column.setLogicalColumnName( name );
column.setSqlType( sqlType );
column.setNullable( ann.nullable() );
column.setBase( ann.base() );
column.setBuildingContext( buildingContext );
column.setPropertyHolder( propertyHolder );
column.bind();
return column;
}
else {
column = new IndexColumn(
true,
null,
0,
0,
0,
null,
true,
false,
true,
true,
null,
null,
propertyHolder,
buildingContext
);
final IndexColumn column = new IndexColumn();
column.setImplicit( true );
column.setBuildingContext( buildingContext );
column.setPropertyHolder( propertyHolder );
column.bind();
return column;
}
return column;
}
}

View File

@ -90,18 +90,16 @@ public class ToOneFkSecondPass extends FkSecondPass {
public void doSecondPass(java.util.Map<String, PersistentClass> persistentClasses) throws MappingException {
if ( value instanceof ManyToOne ) {
ManyToOne manyToOne = (ManyToOne) value;
PersistentClass ref = persistentClasses.get( manyToOne.getReferencedEntityName() );
if ( ref == null ) {
final ManyToOne manyToOne = (ManyToOne) value;
final PersistentClass referencedEntity = persistentClasses.get( manyToOne.getReferencedEntityName() );
if ( referencedEntity == null ) {
throw new AnnotationException( "Association '" + StringHelper.qualify( entityClassName, path )
+ "' targets an unknown entity named '" + manyToOne.getReferencedEntityName() + "'" );
}
manyToOne.setPropertyName( path );
createSyntheticPropertyReference( columns, ref, null, manyToOne, false, buildingContext );
TableBinder.bindForeignKey( ref, null, columns, manyToOne, unique, buildingContext );
/*
* HbmMetadataSourceProcessorImpl does this only when property-ref != null, but IMO, it makes sense event if it is null
*/
createSyntheticPropertyReference( columns, referencedEntity, null, manyToOne, false, 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
if ( !manyToOne.isIgnoreNotFound() ) manyToOne.createPropertyRefConstraints( persistentClasses );
}
else if ( value instanceof OneToOne ) {

View File

@ -178,7 +178,6 @@ import static org.hibernate.internal.util.StringHelper.qualify;
* @author inger
* @author Emmanuel Bernard
*/
@SuppressWarnings("deprecation")
public abstract class CollectionBinder {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, CollectionBinder.class.getName());
@ -284,7 +283,7 @@ public abstract class CollectionBinder {
context
);
CollectionBinder collectionBinder = getCollectionBinder( property, hasMapKeyAnnotation( property ), context );
final CollectionBinder collectionBinder = getCollectionBinder( property, hasMapKeyAnnotation( property ), context );
collectionBinder.setIndexColumn( indexColumn );
collectionBinder.setMapKey( property.getAnnotation( MapKey.class ) );
collectionBinder.setPropertyName( inferredData.getPropertyName() );
@ -315,7 +314,7 @@ public abstract class CollectionBinder {
final PropertyData virtualProperty = property.isAnnotationPresent( ElementCollection.class )
? inferredData
: new WrappedInferredData( inferredData, "element" );
final Comment comment = property.getAnnotation(Comment.class);
final Comment comment = property.getAnnotation( Comment.class );
final AnnotatedColumn[] elementColumns = elementColumns(
propertyHolder,
nullability,
@ -427,12 +426,12 @@ public abstract class CollectionBinder {
collectionBinder.setOneToMany( true );
}
else if ( elementCollectionAnn != null ) {
for ( AnnotatedJoinColumn column : joinColumns) {
for ( AnnotatedJoinColumn column : joinColumns ) {
if ( column.isSecondary() ) {
throw new NotYetImplementedException( "Collections having FK in secondary table" );
}
}
collectionBinder.setFkJoinColumns(joinColumns);
collectionBinder.setFkJoinColumns( joinColumns );
mappedBy = "";
final Class<?> targetElement = elementCollectionAnn.targetClass();
collectionBinder.setTargetEntity( reflectionManager.toXClass( targetElement ) );
@ -462,19 +461,21 @@ public abstract class CollectionBinder {
private static boolean hasMapKeyAnnotation(XProperty property) {
return property.isAnnotationPresent(MapKeyJavaType.class)
|| property.isAnnotationPresent(MapKeyJdbcType.class)
|| property.isAnnotationPresent(MapKeyJdbcTypeCode.class)
|| property.isAnnotationPresent(MapKeyMutability.class)
|| property.isAnnotationPresent(MapKey.class)
|| property.isAnnotationPresent(MapKeyType.class);
|| property.isAnnotationPresent(MapKeyJdbcType.class)
|| property.isAnnotationPresent(MapKeyJdbcTypeCode.class)
|| property.isAnnotationPresent(MapKeyMutability.class)
|| property.isAnnotationPresent(MapKey.class)
|| property.isAnnotationPresent(MapKeyType.class);
}
private static boolean isToManyAssociationWithinEmbeddableCollection(PropertyHolder propertyHolder) {
if(propertyHolder instanceof ComponentPropertyHolder) {
if ( propertyHolder instanceof ComponentPropertyHolder ) {
ComponentPropertyHolder componentPropertyHolder = (ComponentPropertyHolder) propertyHolder;
return componentPropertyHolder.isWithinElementCollection();
}
return false;
else {
return false;
}
}
private static AnnotatedColumn[] elementColumns(
@ -539,8 +540,8 @@ public abstract class CollectionBinder {
CollectionBinder collectionBinder,
Comment comment) {
final jakarta.persistence.Column[] keyColumns = property.isAnnotationPresent(MapKeyColumn.class)
? new jakarta.persistence.Column[] { new MapKeyColumnDelegator( property.getAnnotation(MapKeyColumn.class) ) }
final jakarta.persistence.Column[] keyColumns = property.isAnnotationPresent( MapKeyColumn.class )
? new jakarta.persistence.Column[] { new MapKeyColumnDelegator( property.getAnnotation( MapKeyColumn.class ) ) }
: null;
final AnnotatedColumn[] mapColumns = buildColumnsFromAnnotations(
@ -557,7 +558,7 @@ public abstract class CollectionBinder {
if ( property.isAnnotationPresent( MapKeyJoinColumns.class ) ) {
final MapKeyJoinColumn[] mapKeyJoinColumns = property.getAnnotation( MapKeyJoinColumns.class ).value();
JoinColumn[] joinKeyColumns = new JoinColumn[mapKeyJoinColumns.length];
final JoinColumn[] joinKeyColumns = new JoinColumn[mapKeyJoinColumns.length];
int index = 0;
for ( MapKeyJoinColumn joinColumn : mapKeyJoinColumns ) {
joinKeyColumns[index] = new MapKeyJoinColumnDelegator( joinColumn );
@ -570,13 +571,7 @@ public abstract class CollectionBinder {
return joinKeyColumns;
}
else if ( property.isAnnotationPresent( MapKeyJoinColumn.class ) ) {
return new JoinColumn[] {
new MapKeyJoinColumnDelegator(
property.getAnnotation(
MapKeyJoinColumn.class
)
)
};
return new JoinColumn[] { new MapKeyJoinColumnDelegator( property.getAnnotation( MapKeyJoinColumn.class ) ) };
}
return null;
}
@ -648,7 +643,7 @@ public abstract class CollectionBinder {
annJoins = null;
annInverseJoins = null;
}
AnnotatedJoinColumn[] joinColumns = buildJoinTableJoinColumns(
final AnnotatedJoinColumn[] joinColumns = buildJoinTableJoinColumns(
annJoins,
entityBinder.getSecondaryTables(),
propertyHolder,
@ -656,7 +651,7 @@ public abstract class CollectionBinder {
mappedBy,
buildingContext
);
AnnotatedJoinColumn[] inverseJoinColumns = buildJoinTableJoinColumns(
final AnnotatedJoinColumn[] inverseJoinColumns = buildJoinTableJoinColumns(
annInverseJoins,
entityBinder.getSecondaryTables(),
propertyHolder,
@ -1537,7 +1532,7 @@ public abstract class CollectionBinder {
MetadataBuildingContext buildingContext) {
PersistentClass persistentClass = persistentClasses.get( elementType.getName() );
boolean reversePropertyInJoin = false;
if ( persistentClass != null && isNotEmpty( mappedBy ) ) {
if ( persistentClass != null && hasMappedBy() ) {
try {
reversePropertyInJoin =
0 != persistentClass.getJoinNumber( persistentClass.getRecursiveProperty( mappedBy ) );
@ -1551,11 +1546,11 @@ public abstract class CollectionBinder {
if ( persistentClass != null
&& !reversePropertyInJoin
&& oneToMany
&& !this.isExplicitAssociationTable
&& ( joinColumns[0].isImplicit() && !isEmptyAnnotationValue( this.mappedBy ) //implicit @JoinColumn
|| !fkJoinColumns[0].isImplicit() ) //this is an explicit @JoinColumn
) {
//this is a Foreign key
&& !isExplicitAssociationTable
&& ( joinColumns[0].isImplicit() && hasMappedBy() //implicit @JoinColumn
|| !fkJoinColumns[0].isImplicit() ) //this is an explicit @JoinColumn
) {
//this is a foreign key
bindOneToManySecondPass(
getCollection(),
persistentClasses,
@ -1590,6 +1585,10 @@ public abstract class CollectionBinder {
}
}
private boolean hasMappedBy() {
return isNotEmpty( mappedBy );
}
protected void bindOneToManySecondPass(
Collection collection,
Map<String, PersistentClass> persistentClasses,
@ -1608,16 +1607,16 @@ public abstract class CollectionBinder {
"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() );
collection.setElement( oneToMany );
oneToMany.setReferencedEntityName( collectionType.getName() );
oneToMany.setNotFoundAction( notFoundAction );
String assocClass = oneToMany.getReferencedEntityName();
PersistentClass associatedClass = persistentClasses.get( assocClass );
final String assocClass = oneToMany.getReferencedEntityName();
final PersistentClass associatedClass = persistentClasses.get( assocClass );
handleJpaOrderBy( collection, associatedClass );
Map<String, Join> joins = buildingContext.getMetadataCollector().getJoins( assocClass );
final Map<String, Join> joins = buildingContext.getMetadataCollector().getJoins( assocClass );
if ( associatedClass == null ) {
throw new MappingException(
String.format("Association [%s] for entity [%s] references unmapped class [%s]",
@ -1625,7 +1624,7 @@ public abstract class CollectionBinder {
);
}
oneToMany.setAssociatedClass( associatedClass );
for (AnnotatedJoinColumn column : fkJoinColumns) {
for ( AnnotatedJoinColumn column : fkJoinColumns ) {
column.setPersistentClass( associatedClass, joins, inheritanceStatePerClass );
column.setJoins( joins );
collection.setCollectionTable( column.getTable() );
@ -1646,19 +1645,19 @@ public abstract class CollectionBinder {
buildingContext
);
if ( !collection.isInverse()
&& !collection.getKey().isNullable() ) {
if ( !collection.isInverse() && !collection.getKey().isNullable() ) {
// for non-inverse one-to-many, with a not-null fk, add a backref!
String entityName = oneToMany.getReferencedEntityName();
PersistentClass referenced = buildingContext.getMetadataCollector().getEntityBinding( entityName );
Backref prop = new Backref();
prop.setName( '_' + fkJoinColumns[0].getPropertyName() + '_' + fkJoinColumns[0].getLogicalColumnName() + "Backref" );
prop.setUpdateable( false );
prop.setSelectable( false );
prop.setCollectionRole( collection.getRole() );
prop.setEntityName( collection.getOwner().getEntityName() );
prop.setValue( collection.getKey() );
referenced.addProperty( prop );
final String entityName = oneToMany.getReferencedEntityName();
final PersistentClass referenced = buildingContext.getMetadataCollector().getEntityBinding( entityName );
final Backref backref = new Backref();
AnnotatedJoinColumn fkColumn = fkJoinColumns[0];
backref.setName( '_' + fkColumn.getPropertyName() + '_' + fkColumn.getLogicalColumnName() + "Backref" );
backref.setUpdateable( false );
backref.setSelectable( false );
backref.setCollectionRole( collection.getRole() );
backref.setEntityName( collection.getOwner().getEntityName() );
backref.setValue( collection.getKey() );
referenced.addProperty( backref );
}
}
@ -1698,7 +1697,7 @@ public abstract class CollectionBinder {
}
private void addFilter(boolean hasAssociationTable, Filter filter) {
if (hasAssociationTable) {
if ( hasAssociationTable ) {
collection.addManyToManyFilter(
filter.name(),
getCondition(filter),
@ -1914,7 +1913,7 @@ public abstract class CollectionBinder {
return orderByFragment;
}
private static DependantValue buildCollectionKey(
private DependantValue buildCollectionKey(
Collection collValue,
AnnotatedJoinColumn[] joinColumns,
boolean cascadeDeleteEnabled,
@ -2034,18 +2033,18 @@ public abstract class CollectionBinder {
return key;
}
private static void overrideReferencedPropertyName(
private void overrideReferencedPropertyName(
Collection collValue,
AnnotatedJoinColumn[] joinColumns,
MetadataBuildingContext buildingContext) {
if ( joinColumns.length > 0 ) {
AnnotatedJoinColumn joinColumn = joinColumns[0];
if (isNotEmpty( joinColumn.getMappedBy() )) {
if ( hasMappedBy() ) {
String entityName = joinColumn.getManyToManyOwnerSideEntityName() != null
? "inverse__" + joinColumn.getManyToManyOwnerSideEntityName()
: joinColumn.getPropertyHolder().getEntityName();
InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
String propRef = metadataCollector.getPropertyReferencedAssociation( entityName, joinColumn.getMappedBy() );
String propRef = metadataCollector.getPropertyReferencedAssociation( entityName, mappedBy );
if ( propRef != null ) {
collValue.setReferencedPropertyName( propRef );
metadataCollector.addPropertyReference( collValue.getOwnerEntityName(), propRef );
@ -2090,7 +2089,7 @@ public abstract class CollectionBinder {
isManyToAny
);
if ( !isEmptyAnnotationValue( joinColumns[0].getMappedBy() ) ) {
if ( hasMappedBy() ) {
handleUnownedManyToMany(
collValue,
joinColumns,
@ -2161,7 +2160,7 @@ public abstract class CollectionBinder {
//FIXME: do optional = false
if ( isCollectionOfEntities ) {
bindManytoManyInverseFk( collectionEntity, inverseJoinColumns, element, unique, buildingContext );
bindManyToManyInverseForeignKey( collectionEntity, inverseJoinColumns, element, unique, buildingContext );
}
}
@ -2495,7 +2494,7 @@ public abstract class CollectionBinder {
Property otherSideProperty;
try {
otherSideProperty = collectionEntity.getRecursiveProperty( joinColumns[0].getMappedBy() );
otherSideProperty = collectionEntity.getRecursiveProperty( mappedBy );
}
catch (MappingException e) {
throw new AnnotationException( "Association '" + safeCollectionRole() +
@ -2633,7 +2632,7 @@ public abstract class CollectionBinder {
}
}
private static void bindCollectionSecondPass(
private void bindCollectionSecondPass(
Collection collValue,
PersistentClass collectionEntity,
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
* collection element
* Otherwise delegates to the usual algorithm
* collection element. Otherwise, delegate to the usual algorithm.
*/
public void bindManytoManyInverseFk(
public void bindManyToManyInverseForeignKey(
PersistentClass referencedEntity,
AnnotatedJoinColumn[] columns,
SimpleValue value,
boolean unique,
MetadataBuildingContext buildingContext) {
final String mappedBy = columns[0].getMappedBy();
if ( isNotEmpty( mappedBy ) ) {
if ( hasMappedBy() ) {
final Property property = referencedEntity.getRecursiveProperty( mappedBy );
final List<Selectable> mappedByColumns = mappedByColumns( referencedEntity, property );
for ( Selectable selectable: mappedByColumns ) {

View File

@ -806,23 +806,18 @@ public class EntityBinder {
MetadataBuildingContext context,
InheritanceState inheritanceState,
EntityBinder entityBinder) {
final boolean isRoot = !inheritanceState.hasParents();
DiscriminatorColumn discAnn = clazzToProcess.getAnnotation( DiscriminatorColumn.class );
DiscriminatorType discriminatorType = discAnn != null ? discAnn.discriminatorType() : DiscriminatorType.STRING;
DiscriminatorFormula discFormulaAnn = getOverridableAnnotation( clazzToProcess, DiscriminatorFormula.class, context );
AnnotatedDiscriminatorColumn discriminatorColumn = null;
if ( isRoot ) {
discriminatorColumn = buildDiscriminatorColumn(
discriminatorType,
discAnn,
discFormulaAnn,
context
);
}
final boolean isRoot = !inheritanceState.hasParents();
final AnnotatedDiscriminatorColumn discriminatorColumn = isRoot
? buildDiscriminatorColumn( discriminatorType, discAnn, discFormulaAnn, context )
: null;
if ( discAnn != null && !isRoot ) {
//TODO: shouldn't this be an error?!
LOG.invalidDiscriminatorAnnotation( clazzToProcess.getName() );
}
@ -1808,7 +1803,7 @@ public class EntityBinder {
private void bindJoinToPersistentClass(Join join, AnnotatedJoinColumn[] annotatedJoinColumns, MetadataBuildingContext buildingContext) {
DependantValue key = new DependantValue( buildingContext, join.getTable(), persistentClass.getIdentifier() );
join.setKey( key );
setFKNameIfDefined( join );
setForeignKeyNameIfDefined( join );
key.setCascadeDeleteEnabled( false );
TableBinder.bindForeignKey( persistentClass, null, annotatedJoinColumns, key, false, buildingContext );
key.sortProperties();
@ -1817,7 +1812,7 @@ public class EntityBinder {
persistentClass.addJoin( join );
}
private void setFKNameIfDefined(Join join) {
private void setForeignKeyNameIfDefined(Join join) {
// just awful..
org.hibernate.annotations.Table matchingTable = findMatchingComplementaryTableAnnotation( join );
final SimpleValue key = (SimpleValue) join.getKey();

View File

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

View File

@ -535,6 +535,10 @@ public class PropertyBinder {
this.isId = id;
}
public boolean isId() {
return isId;
}
public void setInheritanceStatePerClass(Map<XClass, InheritanceState> inheritanceStatePerClass) {
this.inheritanceStatePerClass = inheritanceStatePerClass;
}

View File

@ -547,11 +547,10 @@ public class TableBinder {
associatedClass = holder == null ? null : holder.getPersistentClass();
}
final String mappedByProperty = columns[0].getMappedBy();
if ( isNotEmpty( mappedByProperty ) ) {
if ( columns[0].hasMappedBy() ) {
// use the columns of the property referenced by mappedBy
// 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() ) {
// if columns are implicit, then create the columns based
@ -575,20 +574,20 @@ public class TableBinder {
PersistentClass associatedClass) {
switch ( checkReferencedColumnsType( columns, referencedEntity, buildingContext ) ) {
case NON_PK_REFERENCE: {
bindNonPkReference( referencedEntity, columns, value );
bindNonPrimaryKeyReference( referencedEntity, columns, value );
break;
}
case NO_REFERENCE: {
bindImplicitPkReference( referencedEntity, columns, value, associatedClass );
bindImplicitPrimaryKeyReference( referencedEntity, columns, value, associatedClass );
break;
}
default: {
bindPkReference( referencedEntity, columns, value, associatedClass, buildingContext );
bindPrimaryKeyReference( referencedEntity, columns, value, associatedClass, buildingContext );
}
}
}
private static void bindImplicitPkReference(
private static void bindImplicitPrimaryKeyReference(
PersistentClass referencedEntity,
AnnotatedJoinColumn[] columns,
SimpleValue value,
@ -613,7 +612,7 @@ public class TableBinder {
}
}
private static void bindPkReference(
private static void bindPrimaryKeyReference(
PersistentClass referencedEntity,
AnnotatedJoinColumn[] columns,
SimpleValue value,
@ -663,7 +662,7 @@ public class TableBinder {
}
}
private static void bindNonPkReference(
private static void bindNonPrimaryKeyReference(
PersistentClass referencedEntity,
AnnotatedJoinColumn[] columns,
SimpleValue value) {
@ -680,7 +679,6 @@ public class TableBinder {
else {
throw new AnnotationException( "The '@JoinColumn' for a secondary table must reference the primary key" );
}
}
else {
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) {
return string != null && string.length() > 0;
return string != null && !string.isEmpty();
}
public static boolean isEmpty(String string) {

View File

@ -57,7 +57,7 @@ public class AndFormulaTest {
fail( "Expecting failure from invalid mapping" );
}
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.orm.UnclosedFixtureResourcesLogging;
import org.jboss.logging.Logger;
/**
* Metadata about various types of callback methods on a given test class.
*