deprecate some operations of AnnotatedJoinColumn
+ some light refactoring
This commit is contained in:
parent
257bfdb391
commit
f676a1e2af
|
@ -785,6 +785,7 @@ public class AnnotatedColumn {
|
|||
column.setLength( (long) col.length() );
|
||||
column.setPrecision( col.precision() );
|
||||
column.setScale( col.scale() );
|
||||
column.setPropertyHolder( propertyHolder );
|
||||
column.setPropertyName( getRelativePath( propertyHolder, inferredData.getPropertyName() ) );
|
||||
column.setNullable( col.nullable() ); //TODO force to not null if available? This is a (bad) user choice.
|
||||
if ( comment != null ) {
|
||||
|
@ -794,7 +795,6 @@ public class AnnotatedColumn {
|
|||
column.setInsertable( col.insertable() );
|
||||
column.setUpdatable( col.updatable() );
|
||||
column.setExplicitTableName( tableName );
|
||||
column.setPropertyHolder( propertyHolder );
|
||||
column.setJoins( secondaryTables );
|
||||
column.setBuildingContext( context );
|
||||
column.applyColumnDefault( inferredData, length );
|
||||
|
@ -936,10 +936,10 @@ public class AnnotatedColumn {
|
|||
column.setNullable( false );
|
||||
}
|
||||
final String propertyName = inferredData.getPropertyName();
|
||||
column.setPropertyHolder( propertyHolder );
|
||||
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
||||
column.setPropertyHolder(propertyHolder);
|
||||
column.setJoins(secondaryTables);
|
||||
column.setBuildingContext(context);
|
||||
column.setJoins( secondaryTables );
|
||||
column.setBuildingContext( context );
|
||||
// property name + suffix is an "explicit" column name
|
||||
boolean implicit = isEmpty( suffixForDefaultColumnName );
|
||||
if ( !implicit ) {
|
||||
|
@ -1015,10 +1015,13 @@ public class AnnotatedColumn {
|
|||
StringBuilder string = new StringBuilder();
|
||||
string.append( getClass().getSimpleName() ).append( "(" );
|
||||
if ( isNotEmpty( logicalColumnName ) ) {
|
||||
string.append( "column='" ).append( logicalColumnName ).append( "'" );
|
||||
string.append( "column='" ).append( logicalColumnName ).append( "'," );
|
||||
}
|
||||
if ( isNotEmpty( formulaString ) ) {
|
||||
string.append( "formula='" ).append( formulaString ).append( "'" );
|
||||
string.append( "formula='" ).append( formulaString ).append( "'," );
|
||||
}
|
||||
if ( string.charAt( string.length()-1 ) == ',' ) {
|
||||
string.setLength( string.length()-1 );
|
||||
}
|
||||
string.append( ")" );
|
||||
return string.toString();
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.hibernate.boot.model.relational.Database;
|
|||
import org.hibernate.boot.model.source.spi.AttributePath;
|
||||
import org.hibernate.boot.spi.InFlightMetadataCollector;
|
||||
import org.hibernate.boot.spi.MetadataBuildingContext;
|
||||
import org.hibernate.boot.spi.MetadataBuildingOptions;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Join;
|
||||
|
@ -40,7 +41,7 @@ import org.hibernate.mapping.SimpleValue;
|
|||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.mapping.Value;
|
||||
|
||||
import static org.hibernate.cfg.BinderHelper.findColumnOwner;
|
||||
import static org.hibernate.cfg.BinderHelper.findReferencedColumnOwner;
|
||||
import static org.hibernate.cfg.BinderHelper.getRelativePath;
|
||||
import static org.hibernate.cfg.BinderHelper.isEmptyAnnotationValue;
|
||||
import static org.hibernate.cfg.BinderHelper.isEmptyOrNullAnnotationValue;
|
||||
|
@ -54,34 +55,44 @@ import static org.hibernate.internal.util.StringHelper.qualify;
|
|||
* @author Emmanuel Bernard
|
||||
*/
|
||||
public class AnnotatedJoinColumn extends AnnotatedColumn {
|
||||
/**
|
||||
* property name related to this column
|
||||
*/
|
||||
|
||||
private String referencedColumn;
|
||||
private String mappedBy;
|
||||
//property name on the mapped by side if any
|
||||
private String mappedByPropertyName;
|
||||
//table name on the mapped by side if any
|
||||
private String mappedByTableName;
|
||||
private String mappedByEntityName;
|
||||
private String mappedByJpaEntityName;
|
||||
private boolean JPA2ElementCollection;
|
||||
private String manyToManyOwnerSideEntityName;
|
||||
|
||||
//TODO: this is a bad way to determine the ImplicitJoinColumnNameSource.Nature
|
||||
@Deprecated private String mappedBy;
|
||||
@Deprecated private String mappedByPropertyName; //property name on the owning side if any
|
||||
@Deprecated private String mappedByTableName; //table name on the mapped by side if any
|
||||
@Deprecated private String mappedByEntityName;
|
||||
@Deprecated private boolean JPA2ElementCollection;
|
||||
@Deprecated private String manyToManyOwnerSideEntityName;
|
||||
|
||||
// due to @AnnotationOverride overriding rules,
|
||||
// we don't want the constructor to be public
|
||||
private AnnotatedJoinColumn() {
|
||||
mappedBy = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this is not a column-level setting, so it's better to
|
||||
* hang this information somewhere else
|
||||
*/
|
||||
@Deprecated
|
||||
public void setJPA2ElementCollection(boolean JPA2ElementCollection) {
|
||||
this.JPA2ElementCollection = JPA2ElementCollection;
|
||||
}
|
||||
|
||||
//TODO: this is a bad way to get the information at property ref resolution
|
||||
|
||||
/**
|
||||
* @deprecated this is not a column-level setting, so it's better to
|
||||
* get this information from somewhere else
|
||||
*/
|
||||
@Deprecated
|
||||
public String getManyToManyOwnerSideEntityName() {
|
||||
return manyToManyOwnerSideEntityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this is not a column-level setting, so it's better to
|
||||
* get this information from somewhere else
|
||||
*/
|
||||
@Deprecated
|
||||
public void setManyToManyOwnerSideEntityName(String manyToManyOwnerSideEntityName) {
|
||||
this.manyToManyOwnerSideEntityName = manyToManyOwnerSideEntityName;
|
||||
|
@ -91,27 +102,59 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
this.referencedColumn = referencedColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this is not a column-level setting, so it's better to
|
||||
* get this information from somewhere else
|
||||
*/
|
||||
@Deprecated
|
||||
public String getMappedBy() {
|
||||
return mappedBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this is not column-level information, so it's better to
|
||||
* hang all this information somewhere else
|
||||
*/
|
||||
public void setMappedBy(String entityName, String logicalTableName, String mappedByProperty) {
|
||||
mappedByEntityName = entityName;
|
||||
mappedByTableName = logicalTableName;
|
||||
mappedByPropertyName = mappedByProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this is not a column-level setting, so it's better to
|
||||
* hang this information somewhere else
|
||||
*/
|
||||
@Deprecated
|
||||
public void setMappedBy(String mappedBy) {
|
||||
this.mappedBy = mappedBy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the association mapping annotation did specify
|
||||
* {@link jakarta.persistence.OneToMany#mappedBy() mappedBy},
|
||||
* meaning that this {@code @JoinColumn} mapping belongs to an
|
||||
* unowned many-valued association.
|
||||
*/
|
||||
public boolean hasMappedBy() {
|
||||
return isNotEmpty( mappedBy );
|
||||
}
|
||||
|
||||
//Due to @AnnotationOverride overriding rules, I don't want the constructor to be public
|
||||
private AnnotatedJoinColumn() {
|
||||
setMappedBy("");
|
||||
return !isEmptyOrNullAnnotationValue( mappedBy );
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link JoinColumn#referencedColumnName() referencedColumnName}.
|
||||
*/
|
||||
public String getReferencedColumn() {
|
||||
return referencedColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the {@code @JoinColumn} annotation did not specify the
|
||||
* {@link JoinColumn#referencedColumnName() referencedColumnName}.
|
||||
*/
|
||||
public boolean isReferenceImplicit() {
|
||||
return isEmptyOrNullAnnotationValue( referencedColumn );
|
||||
}
|
||||
|
||||
public static AnnotatedJoinColumn[] buildJoinColumnsOrFormulas(
|
||||
JoinColumnOrFormula[] joinColumnOrFormulas,
|
||||
String mappedBy,
|
||||
|
@ -164,8 +207,8 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
formulaColumn.setReferencedColumn(joinFormula.referencedColumnName());
|
||||
formulaColumn.setBuildingContext( buildingContext );
|
||||
formulaColumn.setPropertyHolder( propertyHolder );
|
||||
formulaColumn.setJoins( joins );
|
||||
formulaColumn.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
||||
formulaColumn.setJoins( joins );
|
||||
formulaColumn.bind();
|
||||
return formulaColumn;
|
||||
}
|
||||
|
@ -453,10 +496,11 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
}
|
||||
|
||||
private String buildDefaultColumnName(final PersistentClass referencedEntity, final String logicalReferencedColumn) {
|
||||
final InFlightMetadataCollector metadataCollector = getBuildingContext().getMetadataCollector();
|
||||
final Database database = metadataCollector.getDatabase();
|
||||
final ImplicitNamingStrategy implicitNamingStrategy = getBuildingContext().getBuildingOptions().getImplicitNamingStrategy();
|
||||
final PhysicalNamingStrategy physicalNamingStrategy = getBuildingContext().getBuildingOptions().getPhysicalNamingStrategy();
|
||||
final InFlightMetadataCollector collector = getBuildingContext().getMetadataCollector();
|
||||
final Database database = collector.getDatabase();
|
||||
final MetadataBuildingOptions options = getBuildingContext().getBuildingOptions();
|
||||
final ImplicitNamingStrategy implicitNamingStrategy = options.getImplicitNamingStrategy();
|
||||
final PhysicalNamingStrategy physicalNamingStrategy = options.getPhysicalNamingStrategy();
|
||||
|
||||
boolean mappedBySide = mappedByTableName != null || mappedByPropertyName != null;
|
||||
boolean ownerSide = getPropertyName() != null;
|
||||
|
@ -522,7 +566,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
return null;
|
||||
}
|
||||
|
||||
final Property mappedByProperty = metadataCollector.getEntityBinding( mappedByEntityName )
|
||||
final Property mappedByProperty = collector.getEntityBinding( mappedByEntityName )
|
||||
.getProperty( mappedByPropertyName );
|
||||
final SimpleValue value = (SimpleValue) mappedByProperty.getValue();
|
||||
if ( value.getSelectables().isEmpty() ) {
|
||||
|
@ -542,6 +586,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
String.format(
|
||||
Locale.ENGLISH,
|
||||
"Association '%s' is 'mappedBy' a property '%s' of entity '%s' which maps to a formula",
|
||||
propertyHolder.getPath(),
|
||||
mappedByPropertyName,
|
||||
propertyHolder.getPath()
|
||||
)
|
||||
|
@ -552,6 +597,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
String.format(
|
||||
Locale.ENGLISH,
|
||||
"Association '%s' is 'mappedBy' a property '%s' of entity '%s' with multiple columns",
|
||||
propertyHolder.getPath(),
|
||||
mappedByPropertyName,
|
||||
propertyHolder.getPath()
|
||||
)
|
||||
|
@ -573,7 +619,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
}
|
||||
}
|
||||
else if ( ownerSide ) {
|
||||
final String logicalTableName = metadataCollector.getLogicalTableName( referencedEntity.getTable() );
|
||||
final String logicalTableName = collector.getLogicalTableName( referencedEntity.getTable() );
|
||||
|
||||
columnIdentifier = implicitNamingStrategy.determineJoinColumnName(
|
||||
new ImplicitJoinColumnNameSource() {
|
||||
|
@ -647,7 +693,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
}
|
||||
else {
|
||||
final Identifier logicalTableName = database.toIdentifier(
|
||||
metadataCollector.getLogicalTableName( referencedEntity.getTable() )
|
||||
collector.getLogicalTableName( referencedEntity.getTable() )
|
||||
);
|
||||
|
||||
// is an intra-entity hierarchy table join so copy the name by default
|
||||
|
@ -679,6 +725,11 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
.render( database.getJdbcEnvironment().getDialect() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated this is not a column-level setting, so it's better to
|
||||
* do this work somewhere else
|
||||
*/
|
||||
@Deprecated
|
||||
private ImplicitJoinColumnNameSource.Nature getImplicitNature() {
|
||||
if ( getPropertyHolder().isEntity() ) {
|
||||
return ImplicitJoinColumnNameSource.Nature.ENTITY;
|
||||
|
@ -742,37 +793,34 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
public static final int NON_PK_REFERENCE = 2;
|
||||
|
||||
public static int checkReferencedColumnsType(
|
||||
AnnotatedJoinColumn[] columns,
|
||||
AnnotatedJoinColumn[] joinColumns,
|
||||
PersistentClass referencedEntity,
|
||||
MetadataBuildingContext context) {
|
||||
if ( columns.length == 0 ) {
|
||||
if ( joinColumns.length == 0 ) {
|
||||
return NO_REFERENCE; //shortcut
|
||||
}
|
||||
|
||||
final Object columnOwner = findColumnOwner( referencedEntity, columns[0].getReferencedColumn(), context );
|
||||
final Object columnOwner = findReferencedColumnOwner( referencedEntity, joinColumns[0], context );
|
||||
if ( columnOwner == null ) {
|
||||
try {
|
||||
throw new MappingException(
|
||||
"A '@JoinColumn' references a column named '" + columns[0].getReferencedColumn()
|
||||
+ "' but the target entity '" + referencedEntity.getEntityName()
|
||||
+ "' has no property which maps to this column"
|
||||
);
|
||||
throw new MappingException( "A '@JoinColumn' references a column named '"
|
||||
+ joinColumns[0].getReferencedColumn() + "' but the target entity '"
|
||||
+ referencedEntity.getEntityName() + "' has no property which maps to this column" );
|
||||
}
|
||||
catch (MappingException e) {
|
||||
throw new RecoverableException( e.getMessage(), e );
|
||||
catch (MappingException me) {
|
||||
// we throw a recoverable exception here in case this
|
||||
// is merely an ordering issue, so that the SecondPass
|
||||
// will get reprocessed later
|
||||
throw new RecoverableException( me.getMessage(), me );
|
||||
}
|
||||
}
|
||||
final Table table = columnOwner instanceof PersistentClass
|
||||
? ( (PersistentClass) columnOwner ).getTable()
|
||||
: ( (Join) columnOwner ).getTable();
|
||||
|
||||
final Table table = getTable( columnOwner );
|
||||
final List<Selectable> keyColumns = referencedEntity.getKey().getSelectables();
|
||||
boolean explicitColumnReference = false;
|
||||
for ( AnnotatedJoinColumn column : columns ) {
|
||||
final String logicalReferencedColumnName = column.getReferencedColumn();
|
||||
if ( isNotEmpty( logicalReferencedColumnName ) ) {
|
||||
for ( AnnotatedJoinColumn column : joinColumns ) {
|
||||
if ( !column.isReferenceImplicit() ) {
|
||||
explicitColumnReference = true;
|
||||
if ( !keyColumns.contains( column( context, table, logicalReferencedColumnName ) ) ) {
|
||||
if ( !keyColumns.contains( column( context, table, column.getReferencedColumn() ) ) ) {
|
||||
// we have a column which does not belong to the PK
|
||||
return NON_PK_REFERENCE;
|
||||
}
|
||||
|
@ -780,7 +828,7 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
}
|
||||
if ( explicitColumnReference ) {
|
||||
// if we got to here, all the columns belong to the PK
|
||||
return keyColumns.size() == columns.length
|
||||
return keyColumns.size() == joinColumns.length
|
||||
// we have all the PK columns
|
||||
? PK_REFERENCE
|
||||
// we have a subset of the PK columns
|
||||
|
@ -792,6 +840,12 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
}
|
||||
}
|
||||
|
||||
private static Table getTable(Object persistentClassOrJoin) {
|
||||
return persistentClassOrJoin instanceof PersistentClass
|
||||
? ( (PersistentClass) persistentClassOrJoin ).getTable()
|
||||
: ( (Join) persistentClassOrJoin ).getTable();
|
||||
}
|
||||
|
||||
private static Column column(MetadataBuildingContext context, Table table, String logicalReferencedColumnName) {
|
||||
try {
|
||||
return new Column( context.getMetadataCollector().getPhysicalColumnName( table, logicalReferencedColumnName ) );
|
||||
|
@ -841,9 +895,9 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
column.setImplicit( true );
|
||||
column.setNullable( false ); //I break the spec, but it's for good
|
||||
column.setPropertyHolder( propertyHolder );
|
||||
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
||||
column.setJoins( secondaryTables );
|
||||
column.setBuildingContext( buildingContext );
|
||||
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
||||
column.setMappedBy( mappedBy );
|
||||
column.bind();
|
||||
return new AnnotatedJoinColumn[] { column };
|
||||
|
@ -856,9 +910,9 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
final AnnotatedJoinColumn column = new AnnotatedJoinColumn();
|
||||
column.setImplicit( true );
|
||||
column.setPropertyHolder( propertyHolder );
|
||||
column.setPropertyName( getRelativePath( propertyHolder, propertyName ) );
|
||||
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
|
||||
|
@ -870,22 +924,18 @@ public class AnnotatedJoinColumn extends AnnotatedColumn {
|
|||
}
|
||||
}
|
||||
|
||||
public void setMappedBy(String entityName, String jpaEntityName, String logicalTableName, String mappedByProperty) {
|
||||
this.mappedByEntityName = entityName;
|
||||
this.mappedByJpaEntityName = jpaEntityName;
|
||||
this.mappedByTableName = logicalTableName;
|
||||
this.mappedByPropertyName = mappedByProperty;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder string = new StringBuilder();
|
||||
string.append( getClass().getSimpleName() ).append( "(" );
|
||||
if ( isNotEmpty( getLogicalColumnName() ) ) {
|
||||
string.append( "column='" ).append( getLogicalColumnName() ).append( "'" );
|
||||
string.append( "column='" ).append( getLogicalColumnName() ).append( "'," );
|
||||
}
|
||||
if ( isNotEmpty( referencedColumn ) ) {
|
||||
string.append( "referencedColumn='" ).append( referencedColumn ).append( "'" );
|
||||
string.append( "referencedColumn='" ).append( referencedColumn ).append( "'," );
|
||||
}
|
||||
if ( string.charAt( string.length()-1 ) == ',' ) {
|
||||
string.setLength( string.length()-1 );
|
||||
}
|
||||
string.append( ")" );
|
||||
return string.toString();
|
||||
|
|
|
@ -84,7 +84,6 @@ import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
|||
|
||||
import static org.hibernate.cfg.AnnotatedJoinColumn.NON_PK_REFERENCE;
|
||||
import static org.hibernate.cfg.AnnotatedJoinColumn.checkReferencedColumnsType;
|
||||
import static org.hibernate.internal.util.StringHelper.isEmpty;
|
||||
import static org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies.EMBEDDED;
|
||||
import static org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies.NOOP;
|
||||
import static org.hibernate.property.access.spi.BuiltInPropertyAccessStrategies.interpret;
|
||||
|
@ -180,7 +179,7 @@ public class BinderHelper {
|
|||
// figure out which table has the columns by looking
|
||||
// for a PersistentClass or Join in the hierarchy of
|
||||
// the target entity which has the first column
|
||||
final Object columnOwner = findColumnOwner( targetEntity, columns[0].getReferencedColumn(), context );
|
||||
final Object columnOwner = findReferencedColumnOwner( targetEntity, columns[0], context );
|
||||
checkColumnInSameTable( columns, targetEntity, associatedEntity, context, columnOwner );
|
||||
// find all properties mapped to each column
|
||||
final List<Property> properties = findPropertiesByColumns( columnOwner, columns, associatedEntity, context );
|
||||
|
@ -203,8 +202,6 @@ public class BinderHelper {
|
|||
inverse,
|
||||
associatedEntity,
|
||||
propertyName,
|
||||
// columns[0].getPropertyHolder().getPersistentClass(),
|
||||
// columns[0].getPropertyName(),
|
||||
property.getName(),
|
||||
context
|
||||
);
|
||||
|
@ -228,7 +225,7 @@ public class BinderHelper {
|
|||
// we should only get called for owning side of association
|
||||
throw new AssertionFailure("no need to create synthetic properties for unowned collections");
|
||||
}
|
||||
final Object owner = findColumnOwner( targetEntity, column.getReferencedColumn(), context );
|
||||
final Object owner = findReferencedColumnOwner( targetEntity, column, context );
|
||||
if ( owner == null ) {
|
||||
throw new AnnotationException( "A '@JoinColumn' for association "
|
||||
+ associationMessage( associatedEntity, firstColumn )
|
||||
|
@ -442,13 +439,13 @@ public class BinderHelper {
|
|||
final Map<Column, Set<Property>> columnsToProperty = new HashMap<>();
|
||||
final InFlightMetadataCollector collector = context.getMetadataCollector();
|
||||
for ( AnnotatedJoinColumn joinColumn : columns ) {
|
||||
final String referencedColumn = joinColumn.getReferencedColumn();
|
||||
if ( isEmptyOrNullAnnotationValue( referencedColumn ) ) {
|
||||
if ( joinColumn.isReferenceImplicit() ) {
|
||||
throw new AnnotationException("Association " + associationMessage( associatedEntity, joinColumn )
|
||||
+ " has a '@JoinColumn' which does not specify the 'referencedColumnName'"
|
||||
+ " (when an association has multiple '@JoinColumn's, they must each specify their 'referencedColumnName')");
|
||||
}
|
||||
final Column column = new Column( collector.getPhysicalColumnName( referencedTable, referencedColumn ) );
|
||||
final String name = collector.getPhysicalColumnName( referencedTable, joinColumn.getReferencedColumn() );
|
||||
final Column column = new Column( name );
|
||||
orderedColumns.add( column );
|
||||
columnsToProperty.put( column, new HashSet<>() );
|
||||
}
|
||||
|
@ -697,8 +694,8 @@ public class BinderHelper {
|
|||
if ( propertyHolder == null ) {
|
||||
return propertyName;
|
||||
}
|
||||
String path = propertyHolder.getPath();
|
||||
String entityName = propertyHolder.getPersistentClass().getEntityName();
|
||||
final String path = propertyHolder.getPath();
|
||||
final String entityName = propertyHolder.getPersistentClass().getEntityName();
|
||||
if ( path.length() == entityName.length() ) {
|
||||
return propertyName;
|
||||
}
|
||||
|
@ -707,6 +704,18 @@ public class BinderHelper {
|
|||
}
|
||||
}
|
||||
|
||||
public static Object findReferencedColumnOwner(
|
||||
PersistentClass persistentClass,
|
||||
AnnotatedJoinColumn joinColumn,
|
||||
MetadataBuildingContext context) {
|
||||
if ( joinColumn.isImplicit() || joinColumn.isReferenceImplicit() ) {
|
||||
return persistentClass;
|
||||
}
|
||||
else {
|
||||
return findColumnOwner( persistentClass, joinColumn.getReferencedColumn(), context );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the column owner (ie PersistentClass or Join) of columnName.
|
||||
* If columnName is null or empty, persistentClass is returned
|
||||
|
@ -715,10 +724,6 @@ public class BinderHelper {
|
|||
PersistentClass persistentClass,
|
||||
String columnName,
|
||||
MetadataBuildingContext context) {
|
||||
if ( isEmpty( columnName ) ) {
|
||||
//shortcut for implicit referenced column names
|
||||
return persistentClass;
|
||||
}
|
||||
PersistentClass current = persistentClass;
|
||||
while ( current != null ) {
|
||||
try {
|
||||
|
@ -1023,12 +1028,12 @@ public class BinderHelper {
|
|||
}
|
||||
|
||||
public static boolean isEmptyAnnotationValue(String annotationString) {
|
||||
return annotationString != null && annotationString.length() == 0;
|
||||
return annotationString != null && annotationString.isEmpty();
|
||||
//equivalent to (but faster) ANNOTATION_STRING_DEFAULT.equals( annotationString );
|
||||
}
|
||||
|
||||
public static boolean isEmptyOrNullAnnotationValue(String annotationString) {
|
||||
return annotationString == null || annotationString.length() == 0;
|
||||
return annotationString == null || annotationString.isEmpty();
|
||||
}
|
||||
|
||||
public static String getAnnotationValueStringOrNull(String value) {
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.hibernate.mapping.SimpleValue;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static org.hibernate.cfg.BinderHelper.isEmptyAnnotationValue;
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.mapOfSize;
|
||||
|
||||
/**
|
||||
|
@ -92,14 +91,12 @@ public class CopyIdentifierComponentSecondPass extends FkSecondPass {
|
|||
|
||||
//prepare column name structure
|
||||
boolean isExplicitReference = true;
|
||||
Map<String, AnnotatedJoinColumn> columnByReferencedName = mapOfSize( joinColumns.length);
|
||||
for (AnnotatedJoinColumn joinColumn : joinColumns) {
|
||||
final String referencedColumnName = joinColumn.getReferencedColumn();
|
||||
if ( referencedColumnName == null || isEmptyAnnotationValue( referencedColumnName ) ) {
|
||||
break;
|
||||
final Map<String, AnnotatedJoinColumn> columnByReferencedName = mapOfSize( joinColumns.length );
|
||||
for ( AnnotatedJoinColumn joinColumn : joinColumns ) {
|
||||
if ( !joinColumn.isReferenceImplicit() ) {
|
||||
//JPA 2 requires referencedColumnNames to be case-insensitive
|
||||
columnByReferencedName.put( joinColumn.getReferencedColumn().toLowerCase(Locale.ROOT), joinColumn );
|
||||
}
|
||||
//JPA 2 requires referencedColumnNames to be case-insensitive
|
||||
columnByReferencedName.put( referencedColumnName.toLowerCase(Locale.ROOT), joinColumn );
|
||||
}
|
||||
//try default column orientation
|
||||
if ( columnByReferencedName.isEmpty() ) {
|
||||
|
@ -109,16 +106,28 @@ public class CopyIdentifierComponentSecondPass extends FkSecondPass {
|
|||
}
|
||||
}
|
||||
|
||||
MutableInteger index = new MutableInteger();
|
||||
final MutableInteger index = new MutableInteger();
|
||||
for ( Property referencedProperty : referencedComponent.getProperties() ) {
|
||||
final Property property;
|
||||
if ( referencedProperty.isComposite() ) {
|
||||
Property property = createComponentProperty( referencedPersistentClass, isExplicitReference, columnByReferencedName, index, referencedProperty );
|
||||
component.addProperty( property );
|
||||
property = createComponentProperty(
|
||||
referencedPersistentClass,
|
||||
isExplicitReference,
|
||||
columnByReferencedName,
|
||||
index,
|
||||
referencedProperty
|
||||
);
|
||||
}
|
||||
else {
|
||||
Property property = createSimpleProperty( referencedPersistentClass, isExplicitReference, columnByReferencedName, index, referencedProperty );
|
||||
component.addProperty( property );
|
||||
property = createSimpleProperty(
|
||||
referencedPersistentClass,
|
||||
isExplicitReference,
|
||||
columnByReferencedName,
|
||||
index,
|
||||
referencedProperty
|
||||
);
|
||||
}
|
||||
component.addProperty( property );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1941,20 +1941,20 @@ public abstract class CollectionBinder {
|
|||
}
|
||||
|
||||
private void overrideReferencedPropertyName(
|
||||
Collection collValue,
|
||||
Collection collection,
|
||||
AnnotatedJoinColumn[] joinColumns,
|
||||
MetadataBuildingContext buildingContext) {
|
||||
MetadataBuildingContext context) {
|
||||
if ( joinColumns.length > 0 ) {
|
||||
AnnotatedJoinColumn joinColumn = joinColumns[0];
|
||||
if ( hasMappedBy() ) {
|
||||
String entityName = joinColumn.getManyToManyOwnerSideEntityName() != null
|
||||
final String entityName = joinColumn.getManyToManyOwnerSideEntityName() != null
|
||||
? "inverse__" + joinColumn.getManyToManyOwnerSideEntityName()
|
||||
: joinColumn.getPropertyHolder().getEntityName();
|
||||
InFlightMetadataCollector metadataCollector = buildingContext.getMetadataCollector();
|
||||
String propRef = metadataCollector.getPropertyReferencedAssociation( entityName, mappedBy );
|
||||
if ( propRef != null ) {
|
||||
collValue.setReferencedPropertyName( propRef );
|
||||
metadataCollector.addPropertyReference( collValue.getOwnerEntityName(), propRef );
|
||||
final InFlightMetadataCollector collector = context.getMetadataCollector();
|
||||
final String referencedProperty = collector.getPropertyReferencedAssociation( entityName, mappedBy );
|
||||
if ( referencedProperty != null ) {
|
||||
collection.setReferencedPropertyName( referencedProperty );
|
||||
collector.addPropertyReference( collection.getOwnerEntityName(), referencedProperty );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2309,50 +2309,44 @@ public abstract class CollectionBinder {
|
|||
}
|
||||
|
||||
private void handleOwnedManyToMany(
|
||||
Collection collValue,
|
||||
Collection collection,
|
||||
AnnotatedJoinColumn[] joinColumns,
|
||||
TableBinder associationTableBinder,
|
||||
XProperty property,
|
||||
MetadataBuildingContext buildingContext,
|
||||
MetadataBuildingContext context,
|
||||
PersistentClass collectionEntity,
|
||||
boolean isCollectionOfEntities) {
|
||||
//TODO: only for implicit columns?
|
||||
//FIXME NamingStrategy
|
||||
for (AnnotatedJoinColumn column : joinColumns) {
|
||||
String mappedByProperty = buildingContext.getMetadataCollector().getFromMappedBy(
|
||||
collValue.getOwnerEntityName(), column.getPropertyName()
|
||||
);
|
||||
Table ownerTable = collValue.getOwner().getTable();
|
||||
final InFlightMetadataCollector collector = context.getMetadataCollector();
|
||||
final PersistentClass owner = collection.getOwner();
|
||||
for ( AnnotatedJoinColumn column : joinColumns ) {
|
||||
column.setMappedBy(
|
||||
collValue.getOwner().getEntityName(),
|
||||
collValue.getOwner().getJpaEntityName(),
|
||||
buildingContext.getMetadataCollector().getLogicalTableName( ownerTable ),
|
||||
mappedByProperty
|
||||
owner.getEntityName(),
|
||||
collector.getLogicalTableName( owner.getTable() ),
|
||||
collector.getFromMappedBy( owner.getEntityName(), column.getPropertyName() )
|
||||
);
|
||||
// String header = ( mappedByProperty == null ) ? mappings.getLogicalTableName( ownerTable ) : mappedByProperty;
|
||||
// column.setDefaultColumnHeader( header );
|
||||
}
|
||||
if ( isEmpty( associationTableBinder.getName() ) ) {
|
||||
//default value
|
||||
PersistentClass owner = collValue.getOwner();
|
||||
associationTableBinder.setDefaultName(
|
||||
owner.getClassName(),
|
||||
owner.getEntityName(),
|
||||
owner.getJpaEntityName(),
|
||||
buildingContext.getMetadataCollector().getLogicalTableName( owner.getTable() ),
|
||||
collector.getLogicalTableName( owner.getTable() ),
|
||||
collectionEntity != null ? collectionEntity.getClassName() : null,
|
||||
collectionEntity != null ? collectionEntity.getEntityName() : null,
|
||||
collectionEntity != null ? collectionEntity.getJpaEntityName() : null,
|
||||
collectionEntity != null ? buildingContext.getMetadataCollector().getLogicalTableName(
|
||||
collectionEntity.getTable()
|
||||
) : null,
|
||||
collectionEntity != null ? collector.getLogicalTableName( collectionEntity.getTable() ) : null,
|
||||
joinColumns[0].getPropertyName()
|
||||
);
|
||||
}
|
||||
associationTableBinder.setJPA2ElementCollection(
|
||||
!isCollectionOfEntities && property.isAnnotationPresent(ElementCollection.class)
|
||||
);
|
||||
collValue.setCollectionTable( associationTableBinder.bind() );
|
||||
collection.setCollectionTable( associationTableBinder.bind() );
|
||||
}
|
||||
|
||||
private void handleUnownedManyToMany(
|
||||
|
|
|
@ -533,32 +533,34 @@ public class TableBinder {
|
|||
public static void bindForeignKey(
|
||||
PersistentClass referencedEntity,
|
||||
PersistentClass destinationEntity,
|
||||
AnnotatedJoinColumn[] columns,
|
||||
AnnotatedJoinColumn[] joinColumns,
|
||||
SimpleValue value,
|
||||
boolean unique,
|
||||
MetadataBuildingContext buildingContext) {
|
||||
final AnnotatedJoinColumn firstColumn = joinColumns[0];
|
||||
|
||||
final PersistentClass associatedClass;
|
||||
if ( destinationEntity != null ) {
|
||||
//overridden destination
|
||||
associatedClass = destinationEntity;
|
||||
}
|
||||
else {
|
||||
final PropertyHolder holder = columns[0].getPropertyHolder();
|
||||
final PropertyHolder holder = firstColumn.getPropertyHolder();
|
||||
associatedClass = holder == null ? null : holder.getPersistentClass();
|
||||
}
|
||||
|
||||
if ( columns[0].hasMappedBy() ) {
|
||||
if ( firstColumn.hasMappedBy() ) {
|
||||
// use the columns of the property referenced by mappedBy
|
||||
// copy them and link the copy to the actual value
|
||||
bindUnownedAssociation( columns, value, associatedClass, columns[0].getMappedBy() );
|
||||
bindUnownedAssociation( joinColumns, value, associatedClass, firstColumn.getMappedBy() );
|
||||
}
|
||||
else if ( columns[0].isImplicit() ) {
|
||||
else if ( firstColumn.isImplicit() ) {
|
||||
// if columns are implicit, then create the columns based
|
||||
// on the referenced entity id columns
|
||||
bindImplicitColumns( referencedEntity, columns, value );
|
||||
bindImplicitColumns( referencedEntity, joinColumns, value );
|
||||
}
|
||||
else {
|
||||
bindExplicitColumns( referencedEntity, columns, value, buildingContext, associatedClass );
|
||||
bindExplicitColumns( referencedEntity, joinColumns, value, buildingContext, associatedClass );
|
||||
}
|
||||
value.createForeignKey();
|
||||
if ( unique ) {
|
||||
|
@ -568,44 +570,41 @@ public class TableBinder {
|
|||
|
||||
private static void bindExplicitColumns(
|
||||
PersistentClass referencedEntity,
|
||||
AnnotatedJoinColumn[] columns,
|
||||
AnnotatedJoinColumn[] joinColumns,
|
||||
SimpleValue value,
|
||||
MetadataBuildingContext buildingContext,
|
||||
PersistentClass associatedClass) {
|
||||
switch ( checkReferencedColumnsType( columns, referencedEntity, buildingContext ) ) {
|
||||
case NON_PK_REFERENCE: {
|
||||
bindNonPrimaryKeyReference( referencedEntity, columns, value );
|
||||
switch ( checkReferencedColumnsType( joinColumns, referencedEntity, buildingContext ) ) {
|
||||
case NON_PK_REFERENCE:
|
||||
bindNonPrimaryKeyReference( referencedEntity, joinColumns, value );
|
||||
break;
|
||||
}
|
||||
case NO_REFERENCE: {
|
||||
bindImplicitPrimaryKeyReference( referencedEntity, columns, value, associatedClass );
|
||||
case NO_REFERENCE:
|
||||
bindImplicitPrimaryKeyReference( referencedEntity, joinColumns, value, associatedClass );
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
bindPrimaryKeyReference( referencedEntity, columns, value, associatedClass, buildingContext );
|
||||
}
|
||||
default:
|
||||
bindPrimaryKeyReference( referencedEntity, joinColumns, value, associatedClass, buildingContext );
|
||||
}
|
||||
}
|
||||
|
||||
private static void bindImplicitPrimaryKeyReference(
|
||||
PersistentClass referencedEntity,
|
||||
AnnotatedJoinColumn[] columns,
|
||||
AnnotatedJoinColumn[] joinColumns,
|
||||
SimpleValue value,
|
||||
PersistentClass associatedClass) {
|
||||
//implicit case, we hope PK and FK columns are in the same order
|
||||
if ( columns.length != referencedEntity.getIdentifier().getColumnSpan() ) {
|
||||
if ( joinColumns.length != referencedEntity.getIdentifier().getColumnSpan() ) {
|
||||
// TODO: what about secondary tables?? associatedClass is null?
|
||||
throw new AnnotationException(
|
||||
"An association that targets entity '" + referencedEntity.getEntityName()
|
||||
+ "' from entity '" + associatedClass.getEntityName()
|
||||
+ "' has " + columns.length + " '@JoinColumn's but the primary key has "
|
||||
+ "' has " + joinColumns.length + " '@JoinColumn's but the primary key has "
|
||||
+ referencedEntity.getIdentifier().getColumnSpan() + " columns"
|
||||
);
|
||||
}
|
||||
linkJoinColumnWithValueOverridingNameIfImplicit(
|
||||
referencedEntity,
|
||||
referencedEntity.getIdentifier(),
|
||||
columns,
|
||||
joinColumns,
|
||||
value
|
||||
);
|
||||
if ( value instanceof SortableValue ) {
|
||||
|
@ -615,7 +614,7 @@ public class TableBinder {
|
|||
|
||||
private static void bindPrimaryKeyReference(
|
||||
PersistentClass referencedEntity,
|
||||
AnnotatedJoinColumn[] columns,
|
||||
AnnotatedJoinColumn[] joinColumns,
|
||||
SimpleValue value,
|
||||
PersistentClass associatedClass,
|
||||
MetadataBuildingContext buildingContext) {
|
||||
|
@ -628,23 +627,23 @@ public class TableBinder {
|
|||
// works because the pk has to be on the primary table
|
||||
final Dialect dialect = buildingContext.getMetadataCollector().getDatabase()
|
||||
.getJdbcEnvironment().getDialect();
|
||||
for ( Column col: key.getColumns() ) {
|
||||
for ( Column column: key.getColumns() ) {
|
||||
boolean match = false;
|
||||
// for each PK column, find the associated FK column.
|
||||
final String colName = col.getQuotedName( dialect );
|
||||
for ( AnnotatedJoinColumn joinCol : columns ) {
|
||||
final String quotedName = column.getQuotedName( dialect );
|
||||
for ( AnnotatedJoinColumn joinColumn : joinColumns ) {
|
||||
final String referencedColumn = buildingContext.getMetadataCollector()
|
||||
.getPhysicalColumnName( referencedEntity.getTable(), joinCol.getReferencedColumn() );
|
||||
.getPhysicalColumnName( referencedEntity.getTable(), joinColumn.getReferencedColumn() );
|
||||
// in JPA 2 referencedColumnName is case-insensitive
|
||||
if ( referencedColumn.equalsIgnoreCase( colName ) ) {
|
||||
if ( referencedColumn.equalsIgnoreCase( quotedName ) ) {
|
||||
// correct join column
|
||||
if ( joinCol.isNameDeferred() ) {
|
||||
joinCol.linkValueUsingDefaultColumnNaming( col, referencedEntity, value );
|
||||
if ( joinColumn.isNameDeferred() ) {
|
||||
joinColumn.linkValueUsingDefaultColumnNaming( column, referencedEntity, value );
|
||||
}
|
||||
else {
|
||||
joinCol.linkWithValue( value );
|
||||
joinColumn.linkWithValue( value );
|
||||
}
|
||||
joinCol.overrideFromReferencedColumnIfNecessary( col );
|
||||
joinColumn.overrideFromReferencedColumnIfNecessary( column );
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
|
@ -654,7 +653,7 @@ public class TableBinder {
|
|||
throw new AnnotationException(
|
||||
"An association that targets entity '" + referencedEntity.getEntityName()
|
||||
+ "' from entity '" + associatedClass.getEntityName()
|
||||
+ "' has no '@JoinColumn' referencing column '"+ col.getName()
|
||||
+ "' has no '@JoinColumn' referencing column '"+ column.getName()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -665,14 +664,14 @@ public class TableBinder {
|
|||
|
||||
private static void bindNonPrimaryKeyReference(
|
||||
PersistentClass referencedEntity,
|
||||
AnnotatedJoinColumn[] columns,
|
||||
AnnotatedJoinColumn[] joinColumns,
|
||||
SimpleValue value) {
|
||||
final String referencedPropertyName;
|
||||
if ( value instanceof ToOne ) {
|
||||
referencedPropertyName = ( (ToOne) value).getReferencedPropertyName();
|
||||
}
|
||||
else if ( value instanceof DependantValue ) {
|
||||
final String propertyName = columns[0].getPropertyName();
|
||||
final String propertyName = joinColumns[0].getPropertyName();
|
||||
if ( propertyName != null ) {
|
||||
Collection collection = (Collection) referencedEntity.getRecursiveProperty( propertyName ).getValue();
|
||||
referencedPropertyName = collection.getReferencedPropertyName();
|
||||
|
@ -693,31 +692,31 @@ public class TableBinder {
|
|||
throw new AssertionFailure( "Cannot find synthetic property: "
|
||||
+ referencedEntity.getEntityName() + "." + referencedPropertyName );
|
||||
}
|
||||
linkJoinColumnWithValueOverridingNameIfImplicit( referencedEntity, synthProp.getValue(), columns, value );
|
||||
linkJoinColumnWithValueOverridingNameIfImplicit( referencedEntity, synthProp.getValue(), joinColumns, value );
|
||||
( (SortableValue) value).sortProperties();
|
||||
}
|
||||
|
||||
private static void bindImplicitColumns(
|
||||
PersistentClass referencedEntity,
|
||||
AnnotatedJoinColumn[] columns,
|
||||
AnnotatedJoinColumn[] joinColumns,
|
||||
SimpleValue value) {
|
||||
final List<Column> idColumns = referencedEntity instanceof JoinedSubclass
|
||||
? referencedEntity.getKey().getColumns()
|
||||
: referencedEntity.getIdentifier().getColumns();
|
||||
for ( Column column: idColumns ) {
|
||||
columns[0].linkValueUsingDefaultColumnNaming( column, referencedEntity, value);
|
||||
columns[0].overrideFromReferencedColumnIfNecessary( column );
|
||||
joinColumns[0].linkValueUsingDefaultColumnNaming( column, referencedEntity, value);
|
||||
joinColumns[0].overrideFromReferencedColumnIfNecessary( column );
|
||||
}
|
||||
}
|
||||
|
||||
private static void bindUnownedAssociation(
|
||||
AnnotatedJoinColumn[] columns,
|
||||
AnnotatedJoinColumn[] joinColumns,
|
||||
SimpleValue value,
|
||||
PersistentClass associatedClass,
|
||||
String mappedByProperty) {
|
||||
for ( Column column: mappedByColumns( associatedClass, mappedByProperty ) ) {
|
||||
columns[0].overrideFromReferencedColumnIfNecessary( column );
|
||||
columns[0].linkValueUsingAColumnCopy( column, value);
|
||||
joinColumns[0].overrideFromReferencedColumnIfNecessary( column );
|
||||
joinColumns[0].linkValueUsingAColumnCopy( column, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -740,11 +739,11 @@ public class TableBinder {
|
|||
public static void linkJoinColumnWithValueOverridingNameIfImplicit(
|
||||
PersistentClass referencedEntity,
|
||||
Value value,
|
||||
AnnotatedJoinColumn[] columns,
|
||||
AnnotatedJoinColumn[] joinColumns,
|
||||
SimpleValue simpleValue) {
|
||||
final List<Column> valueColumns = value.getColumns();
|
||||
for ( int i = 0; i < columns.length; i++ ) {
|
||||
final AnnotatedJoinColumn joinCol = columns[i];
|
||||
for ( int i = 0; i < joinColumns.length; i++ ) {
|
||||
final AnnotatedJoinColumn joinCol = joinColumns[i];
|
||||
final Column synthCol = valueColumns.get(i);
|
||||
if ( joinCol.isNameDeferred() ) {
|
||||
//this has to be the default value
|
||||
|
@ -794,11 +793,7 @@ public class TableBinder {
|
|||
else {
|
||||
result = arrayList( annotations.length );
|
||||
for ( UniqueConstraint uc : annotations ) {
|
||||
result.add(
|
||||
new UniqueConstraintHolder()
|
||||
.setName( uc.name() )
|
||||
.setColumns( uc.columnNames() )
|
||||
);
|
||||
result.add( new UniqueConstraintHolder().setName( uc.name() ).setColumns( uc.columnNames() ) );
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
|
@ -537,7 +537,7 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
|
|||
}
|
||||
}
|
||||
|
||||
private Property getRecursiveProperty(String propertyPath, List<Property> iter) throws MappingException {
|
||||
private Property getRecursiveProperty(String propertyPath, List<Property> properties) throws MappingException {
|
||||
Property property = null;
|
||||
StringTokenizer st = new StringTokenizer( propertyPath, ".", false );
|
||||
try {
|
||||
|
@ -565,7 +565,7 @@ public abstract class PersistentClass implements AttributeContainer, Serializabl
|
|||
}
|
||||
|
||||
if ( property == null ) {
|
||||
property = getProperty( element, iter );
|
||||
property = getProperty( element, properties );
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
Loading…
Reference in New Issue