HHH-16423 Improve optional object handling for entity refreshing

This commit is contained in:
Christian Beikov 2023-05-09 12:46:59 +02:00
parent 8786ee8d03
commit 467399437c
14 changed files with 67 additions and 18 deletions

View File

@ -145,13 +145,9 @@ public class CollectionBatchLoaderArrayParam
session.getJdbcServices().getJdbcSelectExecutor().list(
jdbcSelectOperation,
jdbcParameterBindings,
new SingleIdExecutionContext(
null,
null,
null,
LockOptions.NONE,
subSelectFetchableKeysHandler,
session
new ExecutionContextWithSubselectFetchHandler(
session,
subSelectFetchableKeysHandler
),
RowTransformerStandardImpl.instance(),
ListResultsConsumer.UniqueSemantic.FILTER

View File

@ -135,6 +135,7 @@ public class EntityBatchLoaderArrayParam<T>
arrayJdbcMapping,
pkValue,
entityInstance,
getLoadable().getRootEntityDescriptor(),
lockOptions,
readOnly,
session

View File

@ -155,6 +155,7 @@ public class EntityBatchLoaderInPredicate<T>
return new SingleIdExecutionContext(
pkValue,
entityInstance,
getLoadable().getRootEntityDescriptor(),
readOnly,
lockOptions,
registrationHandler,
@ -284,6 +285,7 @@ public class EntityBatchLoaderInPredicate<T>
new SingleIdExecutionContext(
pkValue,
entityInstance,
entityMapping.getRootEntityDescriptor(),
readOnly,
lockOptions,
subSelectFetchableKeysHandler,

View File

@ -24,6 +24,7 @@ import org.hibernate.engine.spi.SubselectFetch;
import org.hibernate.event.spi.EventSource;
import org.hibernate.loader.LoaderLogging;
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
@ -190,6 +191,7 @@ public class LoaderHelper {
JdbcMapping arrayJdbcMapping,
Object entityId,
Object entityInstance,
EntityMappingType rootEntityDescriptor,
LockOptions lockOptions,
Boolean readOnly,
SharedSessionContractImplementor session) {
@ -215,6 +217,7 @@ public class LoaderHelper {
new SingleIdExecutionContext(
entityId,
entityInstance,
rootEntityDescriptor,
readOnly,
lockOptions,
subSelectFetchableKeysHandler,

View File

@ -269,6 +269,7 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
arrayJdbcMapping,
null,
null,
null,
lockOptions,
session.isDefaultReadOnly(),
session

View File

@ -111,6 +111,7 @@ public class MultiNaturalIdLoaderArrayParam<E> implements MultiNaturalIdLoader<E
arrayJdbcMapping,
null,
null,
null,
lockOptions,
session.isDefaultReadOnly(),
session

View File

@ -10,6 +10,7 @@ import java.util.List;
import org.hibernate.LockOptions;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.select.SelectStatement;
@ -24,12 +25,13 @@ import org.hibernate.sql.results.spi.RowTransformer;
public class SingleIdArrayLoadPlan extends SingleIdLoadPlan<Object[]> {
public SingleIdArrayLoadPlan(
EntityMappingType entityMappingType,
ModelPart restrictivePart,
SelectStatement sqlAst,
List<JdbcParameter> jdbcParameters,
LockOptions lockOptions,
SessionFactoryImplementor sessionFactory) {
super( null, restrictivePart, sqlAst, jdbcParameters, lockOptions, sessionFactory );
super( entityMappingType, restrictivePart, sqlAst, jdbcParameters, lockOptions, sessionFactory );
}
@Override

View File

@ -10,6 +10,7 @@ import org.hibernate.LockOptions;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.SubselectFetch;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryOptionsAdapter;
import org.hibernate.sql.exec.internal.BaseExecutionContext;
@ -21,6 +22,7 @@ import org.hibernate.sql.results.graph.entity.LoadingEntityEntry;
class SingleIdExecutionContext extends BaseExecutionContext {
private final Object entityInstance;
private final Object entityId;
private final EntityMappingType rootEntityDescriptor;
private final Boolean readOnly;
private final LockOptions lockOptions;
private final SubselectFetch.RegistrationHandler subSelectFetchableKeysHandler;
@ -28,6 +30,7 @@ class SingleIdExecutionContext extends BaseExecutionContext {
public SingleIdExecutionContext(
Object entityId,
Object entityInstance,
EntityMappingType rootEntityDescriptor,
Boolean readOnly,
LockOptions lockOptions,
SubselectFetch.RegistrationHandler subSelectFetchableKeysHandler,
@ -35,6 +38,7 @@ class SingleIdExecutionContext extends BaseExecutionContext {
super( session );
this.entityInstance = entityInstance;
this.entityId = entityId;
this.rootEntityDescriptor = rootEntityDescriptor;
this.readOnly = readOnly;
this.lockOptions = lockOptions;
this.subSelectFetchableKeysHandler = subSelectFetchableKeysHandler;
@ -50,6 +54,11 @@ class SingleIdExecutionContext extends BaseExecutionContext {
return entityId;
}
@Override
public EntityMappingType getRootEntityDescriptor() {
return rootEntityDescriptor;
}
@Override
public QueryOptions getQueryOptions() {
return new QueryOptionsAdapter() {

View File

@ -145,7 +145,14 @@ public class SingleIdLoadPlan<T> implements SingleEntityLoadPlan {
final List<T> list = session.getJdbcServices().getJdbcSelectExecutor().list(
jdbcSelect,
jdbcParameterBindings,
new SingleIdExecutionContext( session, entityInstance, restrictedValue, queryOptions, callback ),
new SingleIdExecutionContext(
session,
entityInstance,
restrictedValue,
entityMappingType.getRootEntityDescriptor(),
queryOptions,
callback
),
getRowTransformer(),
singleResultExpected ? ListResultsConsumer.UniqueSemantic.ASSERT : ListResultsConsumer.UniqueSemantic.FILTER
);
@ -155,15 +162,14 @@ public class SingleIdLoadPlan<T> implements SingleEntityLoadPlan {
}
final T entity = list.get( 0 );
if ( entityMappingType != null ) {
callback.invokeAfterLoadActions( entity, entityMappingType, session );
}
callback.invokeAfterLoadActions( entity, entityMappingType, session );
return entity;
}
private static class SingleIdExecutionContext extends BaseExecutionContext {
private final Object entityInstance;
private final Object restrictedValue;
private final EntityMappingType rootEntityDescriptor;
private final QueryOptions queryOptions;
private final Callback callback;
@ -171,11 +177,12 @@ public class SingleIdLoadPlan<T> implements SingleEntityLoadPlan {
SharedSessionContractImplementor session,
Object entityInstance,
Object restrictedValue,
QueryOptions queryOptions,
EntityMappingType rootEntityDescriptor, QueryOptions queryOptions,
Callback callback) {
super( session );
this.entityInstance = entityInstance;
this.restrictedValue = restrictedValue;
this.rootEntityDescriptor = rootEntityDescriptor;
this.queryOptions = queryOptions;
this.callback = callback;
}
@ -190,6 +197,11 @@ public class SingleIdLoadPlan<T> implements SingleEntityLoadPlan {
return restrictedValue;
}
@Override
public EntityMappingType getRootEntityDescriptor() {
return rootEntityDescriptor;
}
@Override
public QueryOptions getQueryOptions() {
return queryOptions;

View File

@ -1160,7 +1160,14 @@ public abstract class AbstractEntityPersister
jdbcParameters::add,
factory
);
return new SingleIdArrayLoadPlan( getIdentifierMapping(), select, jdbcParameters, LockOptions.NONE, factory );
return new SingleIdArrayLoadPlan(
this,
getIdentifierMapping(),
select,
jdbcParameters,
LockOptions.NONE,
factory
);
}
}

View File

@ -10,6 +10,7 @@ import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
@ -55,6 +56,10 @@ public interface ExecutionContext {
return null;
}
default EntityMappingType getRootEntityDescriptor() {
return null;
}
default void registerLoadingEntityEntry(EntityKey entityKey, LoadingEntityEntry entry) {
// by default do nothing
}

View File

@ -8,6 +8,7 @@ package org.hibernate.sql.results.graph.embeddable.internal;
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
@ -118,6 +119,11 @@ public class NestedRowProcessingState extends BaseExecutionContext implements Ro
return processingState.getEntityId();
}
@Override
public EntityMappingType getRootEntityDescriptor() {
return processingState.getRootEntityDescriptor();
}
@Override
public void registerLoadingEntityEntry(EntityKey entityKey, LoadingEntityEntry entry) {
processingState.registerLoadingEntityEntry( entityKey, entry );

View File

@ -546,11 +546,9 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
protected Object getEntityInstanceFromExecutionContext(RowProcessingState rowProcessingState) {
final ExecutionContext executionContext = rowProcessingState.getJdbcValuesSourceProcessingState()
.getExecutionContext();
final Object entityInstanceFromExecutionContext = executionContext.getEntityInstance();
if ( entityInstanceFromExecutionContext != null
&& getConcreteDescriptor().getJavaType().isInstance( entityInstanceFromExecutionContext )
if ( rootEntityDescriptor == executionContext.getRootEntityDescriptor()
&& getEntityKey().getIdentifier().equals( executionContext.getEntityId() ) ) {
return entityInstanceFromExecutionContext;
return executionContext.getEntityInstance();
}
return null;
}

View File

@ -8,6 +8,7 @@ package org.hibernate.sql.results.internal;
import org.hibernate.engine.spi.CollectionKey;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.spi.NavigablePath;
import org.hibernate.query.spi.QueryOptions;
@ -166,6 +167,11 @@ public class RowProcessingStateStandardImpl extends BaseExecutionContext impleme
return executionContext.getEntityId();
}
@Override
public EntityMappingType getRootEntityDescriptor() {
return executionContext.getRootEntityDescriptor();
}
@Override
public void registerLoadingEntityEntry(EntityKey entityKey, LoadingEntityEntry entry) {
executionContext.registerLoadingEntityEntry( entityKey, entry );