deprecate some operations of AnnotatedJoinColumn

+ some light refactoring
This commit is contained in:
Gavin King 2022-10-29 13:07:47 +02:00
parent 257bfdb391
commit f676a1e2af
7 changed files with 228 additions and 172 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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