Skip to content

Commit

Permalink
HHH-15969 Inheritance: org.hibernate.PropertyAccessException Exception
Browse files Browse the repository at this point in the history
  • Loading branch information
dreab8 authored and beikov committed Feb 6, 2023
1 parent c1e1be4 commit b2be989
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.Initializer;
import org.hibernate.sql.results.graph.basic.BasicResultAssembler;
import org.hibernate.sql.results.graph.entity.internal.EntityResultInitializer;
import org.hibernate.sql.results.internal.NullValueAssembler;
Expand Down Expand Up @@ -430,6 +431,10 @@ private Object initializeIdentifier(
@Override
public void resolveInstance(RowProcessingState rowProcessingState) {
if ( !missing && !isInitialized ) {
if ( shouldSkipResolveInstance( rowProcessingState ) ) {
missing = true;
return;
}
// Special case map proxy to avoid stack overflows
// We know that a map proxy will always be of "the right type" so just use that object
final LoadingEntityEntry existingLoadingEntry =
Expand All @@ -446,6 +451,62 @@ else if ( existingLoadingEntry != null && existingLoadingEntry.getEntityInitiali
}
}

private boolean shouldSkipResolveInstance(RowProcessingState rowProcessingState) {
final NavigablePath parent = navigablePath.getParent();
if ( parent != null ) {
final Initializer parentInitializer = rowProcessingState.resolveInitializer( parent );
if ( parentInitializer != null && parentInitializer.isEntityInitializer() ) {
if ( isReferencedModelPartAssignableToConcreteParent( parentInitializer ) ) {
return true;
}
}
}
return false;
}

private boolean isReferencedModelPartAssignableToConcreteParent(Initializer parentInitializer) {
final EntityPersister parentConcreteDescriptor = parentInitializer.asEntityInitializer()
.getConcreteDescriptor();
if ( parentConcreteDescriptor != null && parentConcreteDescriptor.getEntityMetamodel().isPolymorphic()) {
final ModelPart concreteModelPart = parentConcreteDescriptor.findByPath( navigablePath.getLocalName() );
if ( concreteModelPart == null
|| !referencedModelPart.getJavaType().getJavaTypeClass()
.isAssignableFrom( concreteModelPart.getJavaType().getJavaTypeClass() ) ) {
/*
Given:
class Message{
@ManyToOne
Address address;
}
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
class Address{
}
class AddressA extends Address {
@OneToOne(mappedBy = "addressA")
UserA userA;
}
class AddressB extends Address{
@OneToOne(mappedBy = "addressB")
UserB userB;
}
when we try to initialize the messages of Message.address,
there will be one EntityJoinedFetchInitializer for UserA and one for UserB so
when resolving AddressA we have to skip resolving the EntityJoinedFetchInitializer of UserB
and for AddressB skip resolving the EntityJoinedFetchInitializer of UserA
*/
return true;
}
}
return false;
}

private void resolveEntityInstance(
RowProcessingState rowProcessingState,
LoadingEntityEntry existingLoadingEntry,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.EntityUniqueKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.spi.EventSource;
Expand Down

0 comments on commit b2be989

Please sign in to comment.