Fix delayed entity fetch loading trying to instantiate abstract class

This commit is contained in:
Andrea Boriero 2021-10-13 09:53:06 +02:00
parent 7eccda9f36
commit 563ee45530
4 changed files with 32 additions and 69 deletions

View File

@ -95,6 +95,7 @@ public class ToOneAttributeMapping
private final String sqlAliasStem;
private final boolean isNullable;
private final boolean isConstrained;
private final boolean isIgnoreNotFound;
private final boolean unwrapProxy;
private final EntityMappingType entityMappingType;
@ -112,6 +113,12 @@ public class ToOneAttributeMapping
private String identifyingColumnsTableExpression;
private boolean canUseParentTableGroup;
private boolean isInternalLoadNullable;
public boolean isInternalLoadNullable(){
return isInternalLoadNullable;
}
public ToOneAttributeMapping(
String name,
NavigableRole navigableRole,
@ -192,6 +199,7 @@ public class ToOneAttributeMapping
else {
this.bidirectionalAttributeName = referencedPropertyName;
}
isInternalLoadNullable = ( (ManyToOne) bootValue ).isIgnoreNotFound();
}
else {
assert bootValue instanceof OneToOne;
@ -257,7 +265,9 @@ public class ToOneAttributeMapping
this.bidirectionalAttributeName = bidirectionalAttributeName;
}
isIgnoreNotFound = isNullable();
isInternalLoadNullable = ! bootValue.isConstrained();
}
isConstrained = bootValue.isConstrained();
this.navigableRole = navigableRole;
final CollectionPart.Nature nature = CollectionPart.Nature.fromNameExact(
@ -343,6 +353,7 @@ public class ToOneAttributeMapping
this.cardinality = original.cardinality;
this.bidirectionalAttributeName = original.bidirectionalAttributeName;
this.declaringTableGroupProducer = original.declaringTableGroupProducer;
this.isConstrained = original.isConstrained;
}
private static void addPrefixedPropertyNames(
@ -1042,6 +1053,10 @@ public class ToOneAttributeMapping
return isNullable;
}
public boolean isConstrained(){
return isConstrained;
}
public boolean isIgnoreNotFound(){
return isIgnoreNotFound;
}

View File

@ -53,7 +53,7 @@ public class EntityDelayedFetchImpl extends AbstractNonJoinedEntityFetch {
getEntityValuedModelPart(),
() -> new EntityDelayedFetchInitializer(
navigablePath,
getEntityValuedModelPart(),
(ToOneAttributeMapping) getEntityValuedModelPart(),
keyResult.createResultAssembler( creationState )
)
);

View File

@ -8,17 +8,12 @@ package org.hibernate.sql.results.graph.entity.internal;
import java.util.function.Consumer;
import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.log.LoggingHelper;
import org.hibernate.loader.entity.CacheEntityLoaderHelper;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.NavigablePath;
@ -35,7 +30,7 @@ import org.hibernate.sql.results.jdbc.spi.RowProcessingState;
public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess implements EntityInitializer {
private final NavigablePath navigablePath;
private final EntityValuedModelPart referencedModelPart;
private final ToOneAttributeMapping referencedModelPart;
private final DomainResultAssembler identifierAssembler;
private Object entityInstance;
@ -43,7 +38,7 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
public EntityDelayedFetchInitializer(
NavigablePath fetchedNavigable,
EntityValuedModelPart referencedModelPart,
ToOneAttributeMapping referencedModelPart,
DomainResultAssembler identifierAssembler) {
this.navigablePath = fetchedNavigable;
this.referencedModelPart = referencedModelPart;
@ -81,69 +76,22 @@ public class EntityDelayedFetchInitializer extends AbstractFetchParentAccess imp
final EntityKey entityKey = new EntityKey( identifier, concreteDescriptor );
final PersistenceContext persistenceContext = rowProcessingState.getSession().getPersistenceContext();
LoadingEntityEntry loadingEntityLocally = persistenceContext
.getLoadContexts().findLoadingEntityEntry( entityKey );
final LoadingEntityEntry loadingEntityLocally = persistenceContext.getLoadContexts().findLoadingEntityEntry(
entityKey );
if ( loadingEntityLocally != null ) {
entityInstance = loadingEntityLocally.getEntityInstance();
}
else {
final Object entity = persistenceContext.getEntity( entityKey );
final Object proxy = persistenceContext.getProxy( entityKey );
if ( entity != null && proxy != null && ( (HibernateProxy) proxy ).getHibernateLazyInitializer()
.isUninitialized() ) {
entityInstance = entity;
}
else {
if ( proxy != null ) {
entityInstance = proxy;
}
else {
if ( entity != null ) {
entityInstance = entity;
}
else {
// Look into the second level cache if the descriptor is polymorphic
final Object cachedEntity;
if ( concreteDescriptor.getEntityMetamodel().hasSubclasses() ) {
cachedEntity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache(
(SharedSessionContractImplementor) rowProcessingState.getSession(),
null,
LockMode.NONE,
concreteDescriptor,
entityKey
);
}
else {
cachedEntity = null;
}
entityInstance = rowProcessingState.getSession().internalLoad(
concreteDescriptor.getEntityName(),
identifier,
false,
referencedModelPart.isInternalLoadNullable()
);
if ( cachedEntity != null ) {
entityInstance = cachedEntity;
}
else {
entityInstance = persistenceContext.getEntity( entityKey );
if ( entityInstance == null ) {
if ( concreteDescriptor.hasProxy() ) {
entityInstance = concreteDescriptor.createProxy(
identifier,
rowProcessingState.getSession()
);
persistenceContext.getBatchFetchQueue().addBatchLoadableEntityKey( entityKey );
persistenceContext.addProxy( entityKey, entityInstance );
}
else if ( concreteDescriptor.getBytecodeEnhancementMetadata()
.isEnhancedForLazyLoading() ) {
entityInstance = concreteDescriptor.getBytecodeEnhancementMetadata()
.createEnhancedProxy(
entityKey,
true,
rowProcessingState.getSession()
);
}
}
}
}
}
if ( entityInstance instanceof HibernateProxy ) {
( (HibernateProxy) entityInstance ).getHibernateLazyInitializer()
.setUnwrap( referencedModelPart.isUnwrapProxy() && concreteDescriptor.isInstrumented() );
}
}

View File

@ -8,7 +8,7 @@ package org.hibernate.sql.results.graph.entity.internal;
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.metamodel.mapping.internal.ToOneAttributeMapping;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.AssemblerCreationState;
@ -65,7 +65,7 @@ public class EntityDelayedResultImpl implements DomainResult {
entityValuedModelPart,
() -> new EntityDelayedFetchInitializer(
getNavigablePath(),
(EntityValuedModelPart) entityValuedModelPart,
(ToOneAttributeMapping) entityValuedModelPart,
identifierResult.createResultAssembler( creationState )
)
);