ToOneAttibuteMapping, Do not consider the referencedPropertyName for the bidirectionalAttributeName determination

This commit is contained in:
Andrea Boriero 2020-06-29 16:43:24 +01:00
parent 3c7a208b96
commit 468989a0f3
7 changed files with 81 additions and 51 deletions

View File

@ -432,8 +432,6 @@ private List<Fetch> visitFetches(FetchParent fetchParent, QuerySpec querySpec, L
} }
final List<Fetch> fetches = new ArrayList<>(); final List<Fetch> fetches = new ArrayList<>();
String fullPath = fetchParent.getNavigablePath().getFullPath();
final BiConsumer<Fetchable, Boolean> processor = createFetchableBiConsumer( fetchParent, querySpec, creationState, fetches ); final BiConsumer<Fetchable, Boolean> processor = createFetchableBiConsumer( fetchParent, querySpec, creationState, fetches );
final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer(); final FetchableContainer referencedMappingContainer = fetchParent.getReferencedMappingContainer();

View File

@ -11,6 +11,7 @@
import org.hibernate.loader.ast.spi.Loadable; import org.hibernate.loader.ast.spi.Loadable;
import org.hibernate.metamodel.mapping.ordering.OrderByFragment; import org.hibernate.metamodel.mapping.ordering.OrderByFragment;
import org.hibernate.persister.collection.CollectionPersister; import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer; import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
import org.hibernate.sql.results.graph.Fetchable; import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer; import org.hibernate.sql.results.graph.FetchableContainer;
@ -56,5 +57,5 @@ default void visitFetchables(Consumer<Fetchable> fetchableConsumer, EntityMappin
String getSeparateCollectionTable(); String getSeparateCollectionTable();
String getBidirectionalPropertyName(); boolean isBidirectionalAttributeName(NavigablePath fetchablePath);
} }

View File

@ -98,7 +98,8 @@ public interface Aware {
private final FetchStyle fetchStyle; private final FetchStyle fetchStyle;
private final CascadeStyle cascadeStyle; private final CascadeStyle cascadeStyle;
private final String bidirectionalPropertyName; private final String bidirectionalAttributeName;
private final Boolean isInverse;
private final CollectionPersister collectionDescriptor; private final CollectionPersister collectionDescriptor;
private final String separateCollectionTable; private final String separateCollectionTable;
@ -175,7 +176,9 @@ public PluralAttributeMappingImpl(
this.cascadeStyle = cascadeStyle; this.cascadeStyle = cascadeStyle;
this.collectionDescriptor = collectionDescriptor; this.collectionDescriptor = collectionDescriptor;
this.bidirectionalPropertyName = StringHelper.subStringNullIfEmpty( bootDescriptor.getMappedByProperty(), '.'); this.bidirectionalAttributeName = StringHelper.subStringNullIfEmpty( bootDescriptor.getMappedByProperty(), '.');
this.isInverse = bootDescriptor.isInverse();
this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( attributeName ); this.sqlAliasStem = SqlAliasStemHelper.INSTANCE.generateStemFromAttributeName( attributeName );
@ -222,6 +225,17 @@ public int getListIndexBase() {
} }
} }
@Override
public boolean isBidirectionalAttributeName(NavigablePath fetchablePath) {
if ( isInverse ) {
return true;
}
if ( bidirectionalAttributeName == null ) {
return false;
}
return fetchablePath.getFullPath().endsWith( bidirectionalAttributeName );
}
@SuppressWarnings("unused") @SuppressWarnings("unused")
public void finishInitialization( public void finishInitialization(
Property bootProperty, Property bootProperty,
@ -393,11 +407,6 @@ public String getSeparateCollectionTable() {
return separateCollectionTable; return separateCollectionTable;
} }
@Override
public String getBidirectionalPropertyName() {
return bidirectionalPropertyName;
}
@Override @Override
public int getStateArrayPosition() { public int getStateArrayPosition() {
return stateArrayPosition; return stateArrayPosition;

View File

@ -76,7 +76,7 @@ public enum Cardinality {
private final boolean referringPrimaryKey; private final boolean referringPrimaryKey;
private final Cardinality cardinality; private final Cardinality cardinality;
private String bidirectionalPropertyName; private String bidirectionalAttributeName;
private ForeignKeyDescriptor foreignKeyDescriptor; private ForeignKeyDescriptor foreignKeyDescriptor;
private ForeignKeyDirection foreignKeyDirection; private ForeignKeyDirection foreignKeyDirection;
@ -170,18 +170,11 @@ class PrimaryKey implements Serializable {
the the navigable path is NavigablePath(Card.fields.{element}.{id}.card) and it does not contain the "primaryKey" part the the navigable path is NavigablePath(Card.fields.{element}.{id}.card) and it does not contain the "primaryKey" part
so in ored to recognize the bidirectionality the "primaryKey." is removed from the otherSidePropertyName value. so in ored to recognize the bidirectionality the "primaryKey." is removed from the otherSidePropertyName value.
*/ */
// todo (6.0): find a better solution for the embeddable part name not in the NavigablePath
String mappedByProperty = StringHelper.subStringNullIfEmpty( bidirectionalAttributeName = StringHelper.subStringNullIfEmpty(
( (OneToOne) bootValue ).getMappedByProperty(), ( (OneToOne) bootValue ).getMappedByProperty(),
'.' '.'
); );
if ( mappedByProperty == null ) {
bidirectionalPropertyName = StringHelper.subStringNullIfEmpty( referencedPropertyName, '.' );
}
else {
bidirectionalPropertyName = mappedByProperty;
}
} }
this.navigableRole = navigableRole; this.navigableRole = navigableRole;
@ -230,19 +223,19 @@ public Fetch resolveCircularFetch(
final AssociationKey associationKey = foreignKeyDescriptor.getAssociationKey(); final AssociationKey associationKey = foreignKeyDescriptor.getAssociationKey();
if ( creationState.isAssociationKeyVisited( associationKey ) ) { if ( creationState.isAssociationKeyVisited( associationKey ) ) {
NavigablePath parent = fetchablePath.getParent(); NavigablePath parentNavigablePath = fetchablePath.getParent();
ModelPart modelPart = creationState.resolveModelPart( parent ); ModelPart modelPart = creationState.resolveModelPart( parentNavigablePath );
if ( modelPart instanceof EmbeddedIdentifierMappingImpl ) { if ( modelPart instanceof EmbeddedIdentifierMappingImpl ) {
while ( parent.getFullPath().endsWith( EntityIdentifierMapping.ROLE_LOCAL_NAME ) ) { while ( parentNavigablePath.getFullPath().endsWith( EntityIdentifierMapping.ROLE_LOCAL_NAME ) ) {
parent = parent.getParent(); parentNavigablePath = parentNavigablePath.getParent();
} }
} }
while ( modelPart instanceof EmbeddableValuedFetchable ) { while ( modelPart instanceof EmbeddableValuedFetchable ) {
parent = parent.getParent(); parentNavigablePath = parentNavigablePath.getParent();
modelPart = creationState.resolveModelPart( parent ); modelPart = creationState.resolveModelPart( parentNavigablePath );
} }
if ( this.bidirectionalPropertyName != null && parent.getFullPath().endsWith( this.bidirectionalPropertyName ) ) { if ( isBidirectionalAttributeName( parentNavigablePath ) ) {
/* /*
class Child { class Child {
@OneToOne(mappedBy = "biologicalChild") @OneToOne(mappedBy = "biologicalChild")
@ -261,7 +254,7 @@ class Mother {
return createCircularBiDirectionalFetch( return createCircularBiDirectionalFetch(
fetchablePath, fetchablePath,
fetchParent, fetchParent,
parent.getParent(), parentNavigablePath,
LockMode.READ LockMode.READ
); );
} }
@ -269,8 +262,13 @@ class Mother {
/* /*
check if mappedBy is on the other side of the association check if mappedBy is on the other side of the association
*/ */
final String otherSideMappedBy = getOthrerSideMappedBy( modelPart, parent.getParent(), creationState ); final boolean isBiDirectional = isBidirectional(
if ( otherSideMappedBy != null ) { modelPart,
parentNavigablePath.getParent(),
fetchablePath,
creationState
);
if ( isBiDirectional ) {
/* /*
class Child { class Child {
@OneToOne(mappedBy = "biologicalChild") @OneToOne(mappedBy = "biologicalChild")
@ -287,16 +285,13 @@ class Mother {
otherSideMappedBy = "biologicalChild" otherSideMappedBy = "biologicalChild"
*/ */
if ( fetchablePath.getFullPath().endsWith( otherSideMappedBy ) ) {
return createCircularBiDirectionalFetch( return createCircularBiDirectionalFetch(
fetchablePath, fetchablePath,
fetchParent, fetchParent,
parent.getParent(), parentNavigablePath,
LockMode.READ LockMode.READ
); );
} }
}
/* /*
class Child { class Child {
@OneToOne @OneToOne
@ -329,37 +324,53 @@ class Mother {
return null; return null;
} }
private String getOthrerSideMappedBy( private boolean isBidirectional(
ModelPart modelPart, ModelPart modelPart,
NavigablePath parentOfParent, NavigablePath parentOfParent,
NavigablePath fetchablePath,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
if ( modelPart instanceof ToOneAttributeMapping ) { if ( modelPart instanceof ToOneAttributeMapping ) {
return ( (ToOneAttributeMapping) modelPart ).getBidirectionalPropertyName(); return ( (ToOneAttributeMapping) modelPart ).isBidirectionalAttributeName( fetchablePath );
} }
if ( modelPart instanceof PluralAttributeMapping ) { if ( modelPart instanceof PluralAttributeMapping ) {
return ( (PluralAttributeMapping) modelPart ).getBidirectionalPropertyName(); return ( (PluralAttributeMapping) modelPart ).isBidirectionalAttributeName( fetchablePath );
} }
if ( modelPart instanceof EntityCollectionPart ) { if ( modelPart instanceof EntityCollectionPart ) {
if ( parentOfParent.getFullPath().endsWith( EntityIdentifierMapping.ROLE_LOCAL_NAME ) ) { if ( parentOfParent.getFullPath().endsWith( EntityIdentifierMapping.ROLE_LOCAL_NAME ) ) {
parentOfParent = parentOfParent.getParent(); parentOfParent = parentOfParent.getParent();
} }
return ( (PluralAttributeMapping) creationState.resolveModelPart( parentOfParent ) ).getBidirectionalPropertyName(); return ( (PluralAttributeMapping) creationState.resolveModelPart( parentOfParent ) ).isBidirectionalAttributeName(
fetchablePath );
} }
return null; return false;
} }
public String getBidirectionalPropertyName(){ protected boolean isBidirectionalAttributeName(NavigablePath fetchablePath) {
return bidirectionalPropertyName; if ( bidirectionalAttributeName == null ) {
return false;
}
return fetchablePath.getFullPath().endsWith( bidirectionalAttributeName );
}
public String getBidirectionalAttributeName(){
return bidirectionalAttributeName;
} }
private Fetch createCircularBiDirectionalFetch( private Fetch createCircularBiDirectionalFetch(
NavigablePath fetchablePath, NavigablePath fetchablePath,
FetchParent fetchParent, FetchParent fetchParent,
NavigablePath referencedNavigablePath, NavigablePath parentNavigablePath,
LockMode lockMode) { LockMode lockMode) {
NavigablePath referencedNavigablePath;
if ( parentNavigablePath.getParent() == null ) {
referencedNavigablePath = parentNavigablePath;
}
else {
referencedNavigablePath = parentNavigablePath.getParent();
}
return new CircularBiDirectionalFetchImpl( return new CircularBiDirectionalFetchImpl(
FetchTiming.IMMEDIATE, FetchTiming.IMMEDIATE,
fetchablePath, fetchablePath,

View File

@ -531,10 +531,10 @@ else if ( persistentClass.isDiscriminatorValueNotNull() ) {
if ( persistentClass.isPolymorphic() ) { if ( persistentClass.isPolymorphic() ) {
subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() ); subclassesByDiscriminatorValue.put( discriminatorValue, getEntityName() );
int initialCapacity = subclassSpan + 1; final int initialCapacity = CollectionHelper.determineProperSizing( subclassSpan + 1 );
discriminatorValuesByTableName = new LinkedHashMap<>( initialCapacity ); discriminatorValuesByTableName = new LinkedHashMap<>( initialCapacity );
discriminatorColumnNameByTableName = new LinkedHashMap<>( initialCapacity ); discriminatorColumnNameByTableName = new LinkedHashMap<>( initialCapacity );
subclassNameByTableName = CollectionHelper.mapOfSize( initialCapacity ); subclassNameByTableName = new HashMap<>( initialCapacity );
// We need to convert the `discriminatorSQLString` (which is a String read from boot-mapping) into // We need to convert the `discriminatorSQLString` (which is a String read from boot-mapping) into
// the type indicated by `#discriminatorType` (String -> Integer, e.g.). // the type indicated by `#discriminatorType` (String -> Integer, e.g.).
try { try {

View File

@ -43,7 +43,7 @@ public void initializeInstance(RowProcessingState rowProcessingState) {
return; return;
} }
final String entityName = concreteDescriptor.getEntityName(); final String entityName = concreteDescriptor.getEntityName();
String uniqueKeyPropertyName = fetchedAttribute.getBidirectionalPropertyName(); String uniqueKeyPropertyName = fetchedAttribute.getBidirectionalAttributeName();
final SharedSessionContractImplementor session = rowProcessingState.getSession(); final SharedSessionContractImplementor session = rowProcessingState.getSession();

View File

@ -15,6 +15,7 @@
import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.Initializer; import org.hibernate.sql.results.graph.Initializer;
import org.hibernate.sql.results.graph.collection.CollectionInitializer; import org.hibernate.sql.results.graph.collection.CollectionInitializer;
import org.hibernate.sql.results.graph.entity.internal.EntityDelayedFetchInitializer;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions; import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState; import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingState;
import org.hibernate.sql.results.jdbc.spi.RowProcessingState; import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
@ -155,7 +156,17 @@ private void coordinateInitializers(
} }
for ( int i = 0; i < numberOfInitializers; i++ ) { for ( int i = 0; i < numberOfInitializers; i++ ) {
initializers.get( i ).resolveInstance( rowProcessingState ); Initializer initializer = initializers.get( i );
if ( !( initializer instanceof EntityDelayedFetchInitializer ) ) {
initializer.resolveInstance( rowProcessingState );
}
}
for ( int i = 0; i < numberOfInitializers; i++ ) {
Initializer initializer = initializers.get( i );
if ( initializer instanceof EntityDelayedFetchInitializer ) {
initializer.resolveInstance( rowProcessingState );
}
} }
for ( int i = 0; i < numberOfInitializers; i++ ) { for ( int i = 0; i < numberOfInitializers; i++ ) {