Skip to content

Commit d4ef44d

Browse files
committed
HHH-18608 NPE in EntityInitializerImpl.resolveInstanceSubInitializers
1 parent 3d767a1 commit d4ef44d

File tree

2 files changed

+29
-2
lines changed

2 files changed

+29
-2
lines changed

hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,7 @@
276276
import org.hibernate.type.ComponentType;
277277
import org.hibernate.type.CompositeType;
278278
import org.hibernate.type.EntityType;
279+
import org.hibernate.type.ManyToOneType;
279280
import org.hibernate.type.Type;
280281
import org.hibernate.type.descriptor.java.JavaType;
281282
import org.hibernate.type.descriptor.java.MutabilityPlan;
@@ -1183,6 +1184,15 @@ private static List<UniqueKeyEntry> initUniqueKeyEntries(final AbstractEntityPer
11831184
uniqueKeys.add( new UniqueKeyEntry( ukName, index, type ) );
11841185
}
11851186
}
1187+
else if ( associationType instanceof ManyToOneType manyToOneType
1188+
&& manyToOneType.isLogicalOneToOne() && manyToOneType.isReferenceToPrimaryKey() ) {
1189+
final AttributeMapping attributeMapping = aep.findAttributeMapping( manyToOneType.getPropertyName() );
1190+
if ( attributeMapping != null ) {
1191+
final int index = attributeMapping.getStateArrayPosition();
1192+
final Type type = aep.getPropertyTypes()[index];
1193+
uniqueKeys.add( new UniqueKeyEntry( manyToOneType.getPropertyName(), index, type ) );
1194+
}
1195+
}
11861196
}
11871197
}
11881198
return toSmallList( uniqueKeys );

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

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.hibernate.cache.spi.access.AccessType;
2424
import org.hibernate.cache.spi.access.EntityDataAccess;
2525
import org.hibernate.cache.spi.entry.CacheEntry;
26+
import org.hibernate.engine.internal.ForeignKeys;
2627
import org.hibernate.engine.spi.EntityEntry;
2728
import org.hibernate.engine.spi.EntityHolder;
2829
import org.hibernate.engine.spi.EntityKey;
@@ -75,6 +76,7 @@
7576
import org.hibernate.sql.results.jdbc.spi.JdbcValuesSourceProcessingOptions;
7677
import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
7778
import org.hibernate.stat.spi.StatisticsImplementor;
79+
import org.hibernate.type.ManyToOneType;
7880
import org.hibernate.type.Type;
7981
import org.hibernate.type.descriptor.java.MutabilityPlan;
8082

@@ -622,6 +624,8 @@ private boolean areKeysEqual(Object key1, Object key2) {
622624
protected void resolveInstanceSubInitializers(EntityInitializerData data) {
623625
final int subclassId = data.concreteDescriptor.getSubclassId();
624626
final EntityEntry entityEntry = data.entityHolder.getEntityEntry();
627+
assert entityEntry != null : "This method should only be called if the entity is already initialized";
628+
625629
final Initializer<?>[] initializers;
626630
final ImmutableBitSet maybeLazySet;
627631
if ( data.entityHolder.getEntityInitializer() == this ) {
@@ -981,11 +985,13 @@ else if ( lazyInitializer.isUninitialized() ) {
981985
registerLoadingEntity( data, data.entityInstanceForNotify );
982986
}
983987
else {
984-
data.setState( State.INITIALIZED );
985988
data.entityInstanceForNotify = lazyInitializer.getImplementation();
986989
data.concreteDescriptor = session.getEntityPersister( null, data.entityInstanceForNotify );
987990
resolveEntityKey( data, lazyInitializer.getIdentifier() );
988991
data.entityHolder = persistenceContext.getEntityHolder( data.entityKey );
992+
// Even though the lazyInitializer reports it is initialized, check if the entity holder reports initialized,
993+
// because in a nested initialization scenario, this nested initializer must initialize the entity
994+
data.setState( data.entityHolder.isInitialized() ? State.INITIALIZED : State.RESOLVED );
989995
}
990996
if ( identifierAssembler != null ) {
991997
final Initializer<?> initializer = identifierAssembler.getInitializer();
@@ -1582,11 +1588,22 @@ protected void registerPossibleUniqueKeyEntries(
15821588
// one used here, which it will be
15831589

15841590
if ( resolvedEntityState[index] != null ) {
1591+
final Object key;
1592+
if ( type instanceof ManyToOneType manyToOneType ) {
1593+
key = ForeignKeys.getEntityIdentifierIfNotUnsaved(
1594+
manyToOneType.getAssociatedEntityName(),
1595+
resolvedEntityState[index],
1596+
session
1597+
);
1598+
}
1599+
else {
1600+
key = resolvedEntityState[index];
1601+
}
15851602
final EntityUniqueKey entityUniqueKey = new EntityUniqueKey(
15861603
data.concreteDescriptor.getRootEntityDescriptor().getEntityName(),
15871604
//polymorphism comment above
15881605
ukName,
1589-
resolvedEntityState[index],
1606+
key,
15901607
type,
15911608
session.getFactory()
15921609
);

0 commit comments

Comments
 (0)