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 @@ public class LoaderSelectBuilder {
} }
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 java.util.function.Consumer;
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 @@ public interface PluralAttributeMapping
String getSeparateCollectionTable(); String getSeparateCollectionTable();
String getBidirectionalPropertyName(); boolean isBidirectionalAttributeName(NavigablePath fetchablePath);
} }

View File

@ -98,7 +98,8 @@ public class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
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 class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
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 class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
} }
} }
@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 class PluralAttributeMappingImpl extends AbstractAttributeMapping impleme
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 class ToOneAttributeMapping extends AbstractSingularAttributeMapping
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 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
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 class ToOneAttributeMapping extends AbstractSingularAttributeMapping
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 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
return createCircularBiDirectionalFetch( return createCircularBiDirectionalFetch(
fetchablePath, fetchablePath,
fetchParent, fetchParent,
parent.getParent(), parentNavigablePath,
LockMode.READ LockMode.READ
); );
} }
@ -269,8 +262,13 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
/* /*
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 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
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 @@ public class ToOneAttributeMapping extends AbstractSingularAttributeMapping
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 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
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 class EntitySelectFetchByUniqueKeyInitializer extends EntitySelectFetchIn
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.LoadingLogger;
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 @@ public class StandardRowReader<T> implements RowReader<T> {
} }
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++ ) {