Skip to content

Commit 147f01a

Browse files
committed
HHH-16812 StackOverflowError an embeddable's @parent is a subclass in an inheritance tree
1 parent d69138f commit 147f01a

File tree

3 files changed

+47
-12
lines changed

3 files changed

+47
-12
lines changed

hibernate-core/src/main/java/org/hibernate/PropertySetterAccessException.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import java.util.Collection;
1010

11+
import org.hibernate.proxy.HibernateProxy;
12+
1113
/**
1214
* @author Steve Ebersole
1315
*/
@@ -47,7 +49,7 @@ public PropertySetterAccessException(
4749
}
4850

4951
public static String loggablePropertyValueString(Object value) {
50-
if ( value instanceof Collection ) {
52+
if ( value instanceof Collection || value instanceof HibernateProxy ) {
5153
return value.getClass().getSimpleName();
5254
}
5355
return value.toString();

hibernate-core/src/main/java/org/hibernate/engine/internal/ManagedTypeHelper.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,17 @@ public static SelfDirtinessTracker asSelfDirtinessTracker(final Object entity) {
375375
throw new ClassCastException( "Object of type '" + entity.getClass() + "' can't be cast to SelfDirtinessTracker" );
376376
}
377377

378+
/**
379+
* Cast the object to an HibernateProxy, or return null in case it is not an instance of HibernateProxy
380+
* @param entity the entity to cast
381+
* @return the same instance after casting or null if it is not an instance of HibernateProxy
382+
*/
383+
public static HibernateProxy asHibernateProxyOrNull(final Object entity) {
384+
return entity instanceof PrimeAmongSecondarySupertypes ?
385+
( (PrimeAmongSecondarySupertypes) entity ).asHibernateProxy() :
386+
null;
387+
}
388+
378389
private static final class TypeMeta {
379390
final boolean isManagedType;
380391
final boolean isSelfDirtinessTrackerType;

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

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77
package org.hibernate.sql.results.graph.embeddable;
88

9+
import org.hibernate.engine.internal.ManagedTypeHelper;
910
import org.hibernate.engine.spi.SessionFactoryImplementor;
1011
import org.hibernate.metamodel.mapping.CompositeIdentifierMapping;
1112
import org.hibernate.metamodel.mapping.EmbeddableMappingType;
@@ -372,7 +373,8 @@ private void handleParentInjection(RowProcessingState processingState) {
372373
return;
373374
}
374375

375-
final Object parent = determineParentInstance( processingState );
376+
Initializer parentInitializer = determineParentInitializer( processingState );
377+
final Object parent = determineParentInstance( parentInitializer );
376378
if ( parent == null ) {
377379
EmbeddableLoadingLogger.EMBEDDED_LOAD_LOGGER.debugf(
378380
"Unable to determine parent for injection into embeddable [%s]",
@@ -388,10 +390,27 @@ private void handleParentInjection(RowProcessingState processingState) {
388390
compositeInstance
389391
);
390392

391-
parentInjectionAccess.getSetter().set( compositeInstance, parent );
393+
394+
final HibernateProxy proxy;
395+
if ( fetchParentAccess != null
396+
&& ( proxy = ManagedTypeHelper.asHibernateProxyOrNull( parent ) ) != null ) {
397+
assert parentInitializer != null;
398+
assert parentInitializer instanceof EntityInitializer;
399+
parentInitializer.asEntityInitializer().registerResolutionListener(
400+
o ->
401+
parentInjectionAccess.getSetter()
402+
.set(
403+
compositeInstance,
404+
proxy.getHibernateLazyInitializer().getImplementation()
405+
)
406+
);
407+
}
408+
else {
409+
parentInjectionAccess.getSetter().set( compositeInstance, parent );
410+
}
392411
}
393412

394-
private Object determineParentInstance(RowProcessingState processingState) {
413+
private Initializer determineParentInitializer(RowProcessingState processingState){
395414
// use `fetchParentAccess` if it is available - it is more efficient
396415
// and the correct way to do it.
397416

@@ -409,31 +428,34 @@ private Object determineParentInstance(RowProcessingState processingState) {
409428
// todo (6.x) - allow injection of containing composite as parent if
410429
// it is the direct parent
411430

412-
final FetchParentAccess firstEntityDescriptorAccess = fetchParentAccess.findFirstEntityDescriptorAccess();
413-
return firstEntityDescriptorAccess.getInitializedInstance();
431+
return fetchParentAccess.findFirstEntityDescriptorAccess();
414432
}
415433

416434
// Otherwise, fallback to determining the parent-initializer by path
417435
// todo (6.0) - this is the part that should be "subsumed" based on the
418436
// comment above
419437

420438
final NavigablePath parentPath = navigablePath.getParent();
421-
if ( parentPath == null ) {
422-
return null;
423-
}
439+
assert parentPath != null;
440+
441+
return processingState.resolveInitializer( parentPath );
442+
}
424443

425-
final Initializer parentInitializer = processingState.resolveInitializer( parentPath );
444+
private Object determineParentInstance(Initializer parentInitializer) {
445+
if ( parentInitializer == null ) {
446+
throw new UnsupportedOperationException( "Cannot determine Embeddable: " + navigablePath + " parent instance, parent initializer is null" );
447+
}
426448

427449
if ( parentInitializer.isCollectionInitializer() ) {
428450
return ( (CollectionInitializer) parentInitializer ).getCollectionInstance().getOwner();
429451
}
430452

431453
final EntityInitializer parentEntityInitializer = parentInitializer.asEntityInitializer();
432454
if ( parentEntityInitializer != null ) {
433-
return parentEntityInitializer.getEntityInstance();
455+
return parentEntityInitializer.getInitializedInstance();
434456
}
435457

436-
throw new UnsupportedOperationException();
458+
throw new UnsupportedOperationException( "The Embeddable: " + navigablePath + " parent initializer is neither an instance of an EntityInitializer nor of a CollectionInitializer" );
437459
}
438460

439461
@Override

0 commit comments

Comments
 (0)