Skip to content

Commit 8312db1

Browse files
mbelladebeikov
authored andcommitted
HHH-16191 Add test and fix checks for skipping resolving polymorphic associated entity instances
1 parent 10bfcab commit 8312db1

File tree

8 files changed

+457
-42
lines changed

8 files changed

+457
-42
lines changed

hibernate-core/src/main/java/org/hibernate/sql/results/graph/Initializer.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,15 @@ default void endLoading(ExecutionContext context) {
7878
default boolean isAttributeAssignableToConcreteDescriptor(
7979
FetchParentAccess parentAccess,
8080
AttributeMapping referencedModelPart) {
81-
if ( parentAccess != null && parentAccess.isEntityInitializer() ) {
82-
final EntityPersister concreteDescriptor = parentAccess.findFirstEntityInitializer()
83-
.getConcreteDescriptor();
81+
final EntityInitializer entityInitializer = parentAccess == null ?
82+
null :
83+
parentAccess.findFirstEntityInitializer();
84+
if ( entityInitializer != null ) {
85+
final EntityPersister concreteDescriptor = entityInitializer.getConcreteDescriptor();
8486
if ( concreteDescriptor.getEntityMetamodel().isPolymorphic() ) {
8587
final EntityPersister declaringType = (EntityPersister) referencedModelPart.getDeclaringType();
8688
if ( concreteDescriptor != declaringType ) {
87-
if ( !declaringType.getSubclassEntityNames().contains( concreteDescriptor.getEntityName() ) ) {
88-
return false;
89-
}
89+
return declaringType.getSubclassEntityNames().contains( concreteDescriptor.getEntityName() );
9090
}
9191
}
9292
}

hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/AbstractEntityInitializer.java

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
9898
private EntityKey entityKey;
9999
private Object entityInstance;
100100
private Object entityInstanceForNotify;
101-
private boolean missing;
101+
protected boolean missing;
102102
boolean isInitialized;
103103
private boolean isOwningInitializer;
104104
private Object[] resolvedEntityState;
@@ -399,26 +399,44 @@ else if ( existingLoadingEntry != null && existingLoadingEntry.getEntityInitiali
399399
}
400400
}
401401

402-
private boolean shouldSkipResolveInstance(RowProcessingState rowProcessingState) {
403-
final NavigablePath parent = navigablePath.getParent();
404-
if ( parent != null ) {
405-
final Initializer parentInitializer = rowProcessingState.resolveInitializer( parent );
406-
if ( parentInitializer != null && parentInitializer.isEntityInitializer() ) {
407-
if ( isReferencedModelPartAssignableToConcreteParent( parentInitializer ) ) {
408-
return true;
402+
protected boolean shouldSkipResolveInstance(RowProcessingState rowProcessingState) {
403+
if ( navigablePath.getParent() != null ) {
404+
Initializer parentInitializer = rowProcessingState.resolveInitializer( navigablePath.getParent() );
405+
if ( parentInitializer != null ) {
406+
ModelPart modelPart = referencedModelPart;
407+
NavigablePath currentNavigablePath = navigablePath;
408+
// Walk back initializers until we find an EntityInitializer
409+
while ( parentInitializer != null && !parentInitializer.isEntityInitializer() ) {
410+
modelPart = parentInitializer.getInitializedPart();
411+
currentNavigablePath = currentNavigablePath.getParent();
412+
parentInitializer = rowProcessingState.resolveInitializer( currentNavigablePath.getParent() );
413+
}
414+
if ( parentInitializer != null && parentInitializer.asEntityInitializer()
415+
.getEntityDescriptor()
416+
.getEntityMetamodel()
417+
.isPolymorphic() ) {
418+
parentInitializer.resolveKey( rowProcessingState );
419+
return isReferencedModelPartInConcreteParent(
420+
modelPart,
421+
currentNavigablePath,
422+
parentInitializer
423+
);
409424
}
410425
}
411426
}
412427
return false;
413428
}
414429

415-
private boolean isReferencedModelPartAssignableToConcreteParent(Initializer parentInitializer) {
430+
private boolean isReferencedModelPartInConcreteParent(
431+
ModelPart modelPart,
432+
NavigablePath partNavigablePath,
433+
Initializer parentInitializer) {
416434
final EntityPersister parentConcreteDescriptor = parentInitializer.asEntityInitializer()
417435
.getConcreteDescriptor();
418-
if ( parentConcreteDescriptor != null && parentConcreteDescriptor.getEntityMetamodel().isPolymorphic()) {
419-
final ModelPart concreteModelPart = parentConcreteDescriptor.findByPath( navigablePath.getLocalName() );
436+
if ( parentConcreteDescriptor != null && parentConcreteDescriptor.getEntityMetamodel().isPolymorphic() ) {
437+
final ModelPart concreteModelPart = parentConcreteDescriptor.findByPath( partNavigablePath.getLocalName() );
420438
if ( concreteModelPart == null
421-
|| !referencedModelPart.getJavaType().getJavaTypeClass()
439+
|| !modelPart.getJavaType().getJavaTypeClass()
422440
.isAssignableFrom( concreteModelPart.getJavaType().getJavaTypeClass() ) ) {
423441
/*
424442
Given:

hibernate-core/src/main/java/org/hibernate/sql/results/graph/entity/internal/EntityJoinedFetchInitializer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ public EntityJoinedFetchInitializer(
7171

7272
@Override
7373
public void resolveKey(RowProcessingState rowProcessingState) {
74+
if ( shouldSkipResolveInstance( rowProcessingState ) ) {
75+
missing = true;
76+
return;
77+
}
78+
7479
super.resolveKey( rowProcessingState );
7580

7681
// super processes the foreign-key target column. here we

hibernate-core/src/test/java/org/hibernate/orm/test/bytecode/enhancement/lazy/proxy/LoadANonExistingNotFoundEntityTest.java

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,8 @@ public void loadEntityWithNotFoundAssociation() {
6767
}
6868
);
6969

70-
// The Employee#employer must be initialized immediately because
71-
// enhanced proxies (and HibernateProxy objects) should never be created
72-
// for a "not found" association.
73-
assertEquals( 2, statistics.getPrepareStatementCount() );
70+
// we should get 1 query for the Employee with join
71+
assertEquals( 1, statistics.getPrepareStatementCount() );
7472
}
7573

7674
@Test
@@ -86,10 +84,8 @@ public void getEntityWithNotFoundAssociation() {
8684
}
8785
);
8886

89-
// The Employee#employer must be initialized immediately because
90-
// enhanced proxies (and HibernateProxy objects) should never be created
91-
// for a "not found" association.
92-
assertEquals( 2, statistics.getPrepareStatementCount() );
87+
// we should get 1 query for the Employee with join
88+
assertEquals( 1, statistics.getPrepareStatementCount() );
9389
}
9490

9591
@Test
@@ -178,7 +174,7 @@ public static class Employee {
178174

179175
private String name;
180176

181-
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
177+
@ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
182178
@JoinColumn(name = "employer_id",foreignKey = @ForeignKey(value= ConstraintMode.NO_CONSTRAINT))
183179
@NotFound(action=NotFoundAction.IGNORE)
184180
private Employer employer;

hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/TransientOverrideAsPersistentMappedSuperclass.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77
package org.hibernate.orm.test.inheritance;
88

99
import java.util.List;
10-
11-
import org.hibernate.annotations.NotFound;
12-
import org.hibernate.annotations.NotFoundAction;
13-
1410
import jakarta.persistence.Column;
1511
import jakarta.persistence.ConstraintMode;
1612
import jakarta.persistence.DiscriminatorColumn;
@@ -307,7 +303,6 @@ public Writer(String name, Group group) {
307303
// Editor#title (which uses the same e_title column) can be non-null,
308304
// and there is no associated group.
309305
@ManyToOne(optional = false)
310-
@NotFound(action = NotFoundAction.IGNORE)
311306
@JoinColumn(name = "e_title", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
312307
public Group getGroup() {
313308
return group;

hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/TransientOverrideAsPersistentSingleTable.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77
package org.hibernate.orm.test.inheritance;
88

99
import java.util.List;
10-
11-
import org.hibernate.annotations.NotFound;
12-
import org.hibernate.annotations.NotFoundAction;
13-
1410
import jakarta.persistence.Column;
1511
import jakarta.persistence.ConstraintMode;
1612
import jakarta.persistence.DiscriminatorColumn;
@@ -300,7 +296,6 @@ public Writer(String name, Group group) {
300296
// Editor#title (which uses the same e_title column) can be non-null,
301297
// and there is no associated group.
302298
@ManyToOne(optional = false)
303-
@NotFound(action = NotFoundAction.IGNORE)
304299
@JoinColumn(name = "e_title", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
305300
public Group getGroup() {
306301
return group;

hibernate-core/src/test/java/org/hibernate/orm/test/inheritance/TransientOverrideAsPersistentTablePerClass.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@
88

99
import java.util.Comparator;
1010
import java.util.List;
11-
12-
import org.hibernate.annotations.NotFound;
13-
import org.hibernate.annotations.NotFoundAction;
14-
1511
import jakarta.persistence.Column;
1612
import jakarta.persistence.ConstraintMode;
1713
import jakarta.persistence.DiscriminatorColumn;
@@ -303,7 +299,6 @@ public Writer(String name, Group group) {
303299
// Editor#title (which uses the same e_title column) can be non-null,
304300
// and there is no associated group.
305301
@ManyToOne(optional = false)
306-
@NotFound(action = NotFoundAction.IGNORE)
307302
@JoinColumn(name = "e_title", foreignKey = @ForeignKey(ConstraintMode.NO_CONSTRAINT))
308303
public Group getGroup() {
309304
return group;

0 commit comments

Comments
 (0)