further cleanups to the Binder code
This commit is contained in:
parent
f4687ac048
commit
86906013c2
|
@ -58,10 +58,7 @@ public abstract class ObjectNameNormalizer {
|
|||
*/
|
||||
public String normalizeIdentifierQuotingAsString(String identifierText) {
|
||||
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) {
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 );
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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 ) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -372,7 +372,7 @@ public class MapBinder extends CollectionBinder {
|
|||
}
|
||||
|
||||
if ( isIndexOfEntities ) {
|
||||
bindManytoManyInverseFk(
|
||||
bindManyToManyInverseForeignKey(
|
||||
collectionEntity,
|
||||
mapKeyManyToManyColumns,
|
||||
element,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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() );
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 " ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue