HHH-14075 : Changes to loaders and TwoPhaseLoad to allow "internal" loading to be reused by hibernate-reactive
This commit is contained in:
parent
9756b0fba8
commit
467203e8c4
|
@ -35,13 +35,13 @@ import org.hibernate.event.spi.PreLoadEventListener;
|
||||||
import org.hibernate.graph.spi.AttributeNodeImplementor;
|
import org.hibernate.graph.spi.AttributeNodeImplementor;
|
||||||
import org.hibernate.graph.spi.GraphImplementor;
|
import org.hibernate.graph.spi.GraphImplementor;
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
import org.hibernate.internal.FastSessionServices;
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
import org.hibernate.persister.entity.EntityPersister;
|
||||||
import org.hibernate.pretty.MessageHelper;
|
import org.hibernate.pretty.MessageHelper;
|
||||||
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
import org.hibernate.property.access.internal.PropertyAccessStrategyBackRefImpl;
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
import org.hibernate.stat.internal.StatsHelper;
|
import org.hibernate.stat.internal.StatsHelper;
|
||||||
import org.hibernate.stat.spi.StatisticsImplementor;
|
import org.hibernate.stat.spi.StatisticsImplementor;
|
||||||
|
import org.hibernate.type.EntityType;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.TypeHelper;
|
import org.hibernate.type.TypeHelper;
|
||||||
|
|
||||||
|
@ -121,18 +121,13 @@ public final class TwoPhaseLoad {
|
||||||
final boolean readOnly,
|
final boolean readOnly,
|
||||||
final SharedSessionContractImplementor session,
|
final SharedSessionContractImplementor session,
|
||||||
final PreLoadEvent preLoadEvent) {
|
final PreLoadEvent preLoadEvent) {
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContext();
|
|
||||||
final EntityEntry entityEntry = persistenceContext.getEntry( entity );
|
|
||||||
if ( entityEntry == null ) {
|
|
||||||
throw new AssertionFailure( "possible non-threadsafe access to the session" );
|
|
||||||
}
|
|
||||||
final EventListenerGroup<PreLoadEventListener> listenerGroup = session
|
final EventListenerGroup<PreLoadEventListener> listenerGroup = session
|
||||||
.getFactory()
|
.getFactory()
|
||||||
.getServiceRegistry()
|
.getServiceRegistry()
|
||||||
.getService( EventListenerRegistry.class )
|
.getService( EventListenerRegistry.class )
|
||||||
.getEventListenerGroup( EventType.PRE_LOAD );
|
.getEventListenerGroup( EventType.PRE_LOAD );
|
||||||
final Iterable<PreLoadEventListener> listeners = listenerGroup.listeners();
|
final Iterable<PreLoadEventListener> listeners = listenerGroup.listeners();
|
||||||
doInitializeEntity( entity, entityEntry, readOnly, session, preLoadEvent, listeners );
|
initializeEntity( entity, readOnly, session, preLoadEvent, listeners, EntityResolver.DEFAULT );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -155,22 +150,46 @@ public final class TwoPhaseLoad {
|
||||||
final SharedSessionContractImplementor session,
|
final SharedSessionContractImplementor session,
|
||||||
final PreLoadEvent preLoadEvent,
|
final PreLoadEvent preLoadEvent,
|
||||||
final Iterable<PreLoadEventListener> preLoadEventListeners) {
|
final Iterable<PreLoadEventListener> preLoadEventListeners) {
|
||||||
|
initializeEntity( entity, readOnly, session, preLoadEvent, preLoadEventListeners, EntityResolver.DEFAULT );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform the second step of 2-phase load. Fully initialize the entity
|
||||||
|
* instance.
|
||||||
|
* <p/>
|
||||||
|
* After processing a JDBC result set, we "resolve" all the associations
|
||||||
|
* between the entities which were instantiated and had their state
|
||||||
|
* "hydrated" into an array
|
||||||
|
*
|
||||||
|
* @param entity The entity being loaded
|
||||||
|
* @param readOnly Is the entity being loaded as read-only
|
||||||
|
* @param session The Session
|
||||||
|
* @param preLoadEvent The (re-used) pre-load event
|
||||||
|
* @param preLoadEventListeners the pre-load event listeners
|
||||||
|
* @param entityResolver the resolver used for to-one entity associations
|
||||||
|
* (not used when an entity is a bytecode-enhanced lazy entity)
|
||||||
|
*/
|
||||||
|
public static void initializeEntity(
|
||||||
|
final Object entity,
|
||||||
|
final boolean readOnly,
|
||||||
|
final SharedSessionContractImplementor session,
|
||||||
|
final PreLoadEvent preLoadEvent,
|
||||||
|
final Iterable<PreLoadEventListener> preLoadEventListeners,
|
||||||
|
final EntityResolver entityResolver) {
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
||||||
final EntityEntry entityEntry = persistenceContext.getEntry( entity );
|
final EntityEntry entityEntry = persistenceContext.getEntry( entity );
|
||||||
if ( entityEntry == null ) {
|
if ( entityEntry == null ) {
|
||||||
throw new AssertionFailure( "possible non-threadsafe access to the session" );
|
throw new AssertionFailure( "possible non-threadsafe access to the session" );
|
||||||
}
|
}
|
||||||
doInitializeEntity( entity, entityEntry, readOnly, session, preLoadEvent, preLoadEventListeners );
|
initializeEntityEntryLoadedState( entity, entityEntry, session, entityResolver );
|
||||||
|
initializeEntityFromEntityEntryLoadedState( entity, entityEntry, readOnly, session, preLoadEvent, preLoadEventListeners );
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void doInitializeEntity(
|
public static void initializeEntityEntryLoadedState(
|
||||||
final Object entity,
|
final Object entity,
|
||||||
final EntityEntry entityEntry,
|
final EntityEntry entityEntry,
|
||||||
final boolean readOnly,
|
|
||||||
final SharedSessionContractImplementor session,
|
final SharedSessionContractImplementor session,
|
||||||
final PreLoadEvent preLoadEvent,
|
final EntityResolver entityResolver) throws HibernateException {
|
||||||
final Iterable<PreLoadEventListener> preLoadEventListeners) throws HibernateException {
|
|
||||||
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
|
||||||
final EntityPersister persister = entityEntry.getPersister();
|
final EntityPersister persister = entityEntry.getPersister();
|
||||||
final Serializable id = entityEntry.getId();
|
final Serializable id = entityEntry.getId();
|
||||||
final Object[] hydratedState = entityEntry.getLoadedState();
|
final Object[] hydratedState = entityEntry.getLoadedState();
|
||||||
|
@ -229,18 +248,36 @@ public final class TwoPhaseLoad {
|
||||||
|
|
||||||
// we know value != LazyPropertyInitializer.UNFETCHED_PROPERTY
|
// we know value != LazyPropertyInitializer.UNFETCHED_PROPERTY
|
||||||
Boolean overridingEager = getOverridingEager( session, entityName, propertyNames[i], types[i], debugEnabled );
|
Boolean overridingEager = getOverridingEager( session, entityName, propertyNames[i], types[i], debugEnabled );
|
||||||
hydratedState[i] = types[i].resolve( value, session, entity, overridingEager );
|
hydratedState[i] = types[i].isEntityType()
|
||||||
|
? entityResolver.resolve( (EntityType) types[i], value, session, entity, overridingEager )
|
||||||
|
: types[i].resolve( value, session, entity, overridingEager );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ( debugEnabled ) {
|
if ( debugEnabled ) {
|
||||||
LOG.debugf( "Skipping <unknown> attribute : `%s`", propertyNames[i] );
|
LOG.debugf( "Skipping <unknown> attribute : `%s`", propertyNames[i] );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( session.getFetchGraphLoadContext() != fetchGraphContext ) {
|
if ( session.getFetchGraphLoadContext() != fetchGraphContext ) {
|
||||||
session.setFetchGraphLoadContext( fetchGraphContext );
|
session.setFetchGraphLoadContext( fetchGraphContext );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void initializeEntityFromEntityEntryLoadedState(
|
||||||
|
final Object entity,
|
||||||
|
final EntityEntry entityEntry,
|
||||||
|
final boolean readOnly,
|
||||||
|
final SharedSessionContractImplementor session,
|
||||||
|
final PreLoadEvent preLoadEvent,
|
||||||
|
final Iterable<PreLoadEventListener> preLoadEventListeners) throws HibernateException {
|
||||||
|
|
||||||
|
final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
|
||||||
|
final EntityPersister persister = entityEntry.getPersister();
|
||||||
|
final Serializable id = entityEntry.getId();
|
||||||
|
final Object[] hydratedState = entityEntry.getLoadedState();
|
||||||
|
|
||||||
|
final boolean debugEnabled = LOG.isDebugEnabled();
|
||||||
|
|
||||||
//Must occur after resolving identifiers!
|
//Must occur after resolving identifiers!
|
||||||
if ( session.isEventSource() ) {
|
if ( session.isEventSource() ) {
|
||||||
|
@ -600,4 +637,23 @@ public final class TwoPhaseLoad {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementations determine how a to-one associations is resolved.
|
||||||
|
*
|
||||||
|
* @see #initializeEntity(Object, boolean, SharedSessionContractImplementor, PreLoadEvent, Iterable, EntityResolver)
|
||||||
|
*/
|
||||||
|
public interface EntityResolver {
|
||||||
|
|
||||||
|
Object resolve(
|
||||||
|
EntityType entityType,
|
||||||
|
Object value,
|
||||||
|
SharedSessionContractImplementor session,
|
||||||
|
Object owner,
|
||||||
|
Boolean overridingEager
|
||||||
|
);
|
||||||
|
|
||||||
|
EntityResolver DEFAULT = (entityType, value, session, owner, overridingEager) ->
|
||||||
|
entityType.resolve( value, session, owner, overridingEager );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -986,12 +986,48 @@ public abstract class Loader {
|
||||||
int maxRows,
|
int maxRows,
|
||||||
List<AfterLoadAction> afterLoadActions) throws SQLException {
|
List<AfterLoadAction> afterLoadActions) throws SQLException {
|
||||||
final int entitySpan = getEntityPersisters().length;
|
final int entitySpan = getEntityPersisters().length;
|
||||||
|
final boolean createSubselects = isSubselectLoadingEnabled();
|
||||||
|
final List<EntityKey[]> subselectResultKeys = createSubselects ? new ArrayList<>() : null;
|
||||||
|
final List<Object> hydratedObjects = entitySpan == 0 ? null : new ArrayList<>( entitySpan * 10 );
|
||||||
|
|
||||||
|
final List results = getRowsFromResultSet(
|
||||||
|
rs,
|
||||||
|
queryParameters,
|
||||||
|
session,
|
||||||
|
returnProxies,
|
||||||
|
forcedResultTransformer,
|
||||||
|
maxRows,
|
||||||
|
hydratedObjects,
|
||||||
|
subselectResultKeys
|
||||||
|
);
|
||||||
|
|
||||||
|
initializeEntitiesAndCollections(
|
||||||
|
hydratedObjects,
|
||||||
|
rs,
|
||||||
|
session,
|
||||||
|
queryParameters.isReadOnly( session ),
|
||||||
|
afterLoadActions
|
||||||
|
);
|
||||||
|
if ( createSubselects ) {
|
||||||
|
createSubselects( subselectResultKeys, queryParameters, session );
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Object> getRowsFromResultSet(
|
||||||
|
ResultSet rs,
|
||||||
|
QueryParameters queryParameters,
|
||||||
|
SharedSessionContractImplementor session,
|
||||||
|
boolean returnProxies,
|
||||||
|
ResultTransformer forcedResultTransformer,
|
||||||
|
int maxRows,
|
||||||
|
List<Object> hydratedObjects,
|
||||||
|
List<EntityKey[]> subselectResultKeys) throws SQLException {
|
||||||
|
final int entitySpan = getEntityPersisters().length;
|
||||||
|
final boolean createSubselects = isSubselectLoadingEnabled();
|
||||||
final EntityKey optionalObjectKey = getOptionalObjectKey( queryParameters, session );
|
final EntityKey optionalObjectKey = getOptionalObjectKey( queryParameters, session );
|
||||||
final LockMode[] lockModesArray = getLockModes( queryParameters.getLockOptions() );
|
final LockMode[] lockModesArray = getLockModes( queryParameters.getLockOptions() );
|
||||||
final boolean createSubselects = isSubselectLoadingEnabled();
|
final List<Object> results = new ArrayList<>();
|
||||||
final List subselectResultKeys = createSubselects ? new ArrayList() : null;
|
|
||||||
final ArrayList hydratedObjects = entitySpan == 0 ? null : new ArrayList( entitySpan * 10 );
|
|
||||||
final List results = new ArrayList();
|
|
||||||
|
|
||||||
handleEmptyCollections( queryParameters.getCollectionKeys(), rs, session );
|
handleEmptyCollections( queryParameters.getCollectionKeys(), rs, session );
|
||||||
EntityKey[] keys = new EntityKey[entitySpan]; //we can reuse it for each row
|
EntityKey[] keys = new EntityKey[entitySpan]; //we can reuse it for each row
|
||||||
|
@ -1023,16 +1059,6 @@ public abstract class Loader {
|
||||||
|
|
||||||
LOG.tracev( "Done processing result set ({0} rows)", count );
|
LOG.tracev( "Done processing result set ({0} rows)", count );
|
||||||
|
|
||||||
initializeEntitiesAndCollections(
|
|
||||||
hydratedObjects,
|
|
||||||
rs,
|
|
||||||
session,
|
|
||||||
queryParameters.isReadOnly( session ),
|
|
||||||
afterLoadActions
|
|
||||||
);
|
|
||||||
if ( createSubselects ) {
|
|
||||||
createSubselects( subselectResultKeys, queryParameters, session );
|
|
||||||
}
|
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1061,7 +1087,7 @@ public abstract class Loader {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createSubselects(List keys, QueryParameters queryParameters, SharedSessionContractImplementor session) {
|
protected void createSubselects(List keys, QueryParameters queryParameters, SharedSessionContractImplementor session) {
|
||||||
if ( keys.size() > 1 ) { //if we only returned one entity, query by key is more efficient
|
if ( keys.size() > 1 ) { //if we only returned one entity, query by key is more efficient
|
||||||
|
|
||||||
Set[] keySets = transpose( keys );
|
Set[] keySets = transpose( keys );
|
||||||
|
|
|
@ -62,7 +62,7 @@ public abstract class OuterJoinLoader extends BasicLoader {
|
||||||
return sql;
|
return sql;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final Loadable[] getEntityPersisters() {
|
public final Loadable[] getEntityPersisters() {
|
||||||
return persisters;
|
return persisters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ public abstract class OuterJoinLoader extends BasicLoader {
|
||||||
return aliases;
|
return aliases;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected final CollectionPersister[] getCollectionPersisters() {
|
public final CollectionPersister[] getCollectionPersisters() {
|
||||||
return collectionPersisters;
|
return collectionPersisters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.loader.plan.build.spi.MetamodelDrivenLoadPlanBuilder;
|
||||||
import org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader;
|
import org.hibernate.loader.plan.exec.internal.AbstractLoadPlanBasedLoader;
|
||||||
import org.hibernate.loader.plan.exec.internal.BatchingLoadQueryDetailsFactory;
|
import org.hibernate.loader.plan.exec.internal.BatchingLoadQueryDetailsFactory;
|
||||||
import org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails;
|
import org.hibernate.loader.plan.exec.internal.EntityLoadQueryDetails;
|
||||||
|
import org.hibernate.loader.plan.exec.process.spi.ResultSetProcessorResolver;
|
||||||
import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters;
|
import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters;
|
||||||
import org.hibernate.loader.plan.exec.spi.LoadQueryDetails;
|
import org.hibernate.loader.plan.exec.spi.LoadQueryDetails;
|
||||||
import org.hibernate.loader.plan.spi.LoadPlan;
|
import org.hibernate.loader.plan.spi.LoadPlan;
|
||||||
|
@ -58,7 +59,8 @@ public abstract class AbstractLoadPlanBasedEntityLoader extends AbstractLoadPlan
|
||||||
SessionFactoryImplementor factory,
|
SessionFactoryImplementor factory,
|
||||||
String[] uniqueKeyColumnNames,
|
String[] uniqueKeyColumnNames,
|
||||||
Type uniqueKeyType,
|
Type uniqueKeyType,
|
||||||
QueryBuildingParameters buildingParameters) {
|
QueryBuildingParameters buildingParameters,
|
||||||
|
ResultSetProcessorResolver resultSetProcessorResolver) {
|
||||||
super( factory );
|
super( factory );
|
||||||
this.entityPersister = entityPersister;
|
this.entityPersister = entityPersister;
|
||||||
this.uniqueKeyType = uniqueKeyType;
|
this.uniqueKeyType = uniqueKeyType;
|
||||||
|
@ -96,7 +98,42 @@ public abstract class AbstractLoadPlanBasedEntityLoader extends AbstractLoadPlan
|
||||||
plan,
|
plan,
|
||||||
uniqueKeyColumnNames,
|
uniqueKeyColumnNames,
|
||||||
buildingParameters,
|
buildingParameters,
|
||||||
factory
|
factory,
|
||||||
|
resultSetProcessorResolver
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractLoadPlanBasedEntityLoader(
|
||||||
|
OuterJoinLoadable entityPersister,
|
||||||
|
SessionFactoryImplementor factory,
|
||||||
|
String[] uniqueKeyColumnNames,
|
||||||
|
Type uniqueKeyType,
|
||||||
|
QueryBuildingParameters buildingParameters) {
|
||||||
|
this(
|
||||||
|
entityPersister,
|
||||||
|
factory,
|
||||||
|
uniqueKeyColumnNames,
|
||||||
|
uniqueKeyType,
|
||||||
|
buildingParameters,ResultSetProcessorResolver.DEFAULT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractLoadPlanBasedEntityLoader(
|
||||||
|
OuterJoinLoadable entityPersister,
|
||||||
|
SessionFactoryImplementor factory,
|
||||||
|
EntityLoadQueryDetails entityLoaderQueryDetailsTemplate,
|
||||||
|
Type uniqueKeyType,
|
||||||
|
QueryBuildingParameters buildingParameters,
|
||||||
|
ResultSetProcessorResolver resultSetProcessorResolver) {
|
||||||
|
super( factory );
|
||||||
|
this.entityPersister = entityPersister;
|
||||||
|
this.uniqueKeyType = uniqueKeyType;
|
||||||
|
this.entityName = entityPersister.getEntityName();
|
||||||
|
|
||||||
|
this.staticLoadQuery = BatchingLoadQueryDetailsFactory.INSTANCE.makeEntityLoadQueryDetails(
|
||||||
|
entityLoaderQueryDetailsTemplate,
|
||||||
|
buildingParameters,
|
||||||
|
resultSetProcessorResolver
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,14 +143,13 @@ public abstract class AbstractLoadPlanBasedEntityLoader extends AbstractLoadPlan
|
||||||
EntityLoadQueryDetails entityLoaderQueryDetailsTemplate,
|
EntityLoadQueryDetails entityLoaderQueryDetailsTemplate,
|
||||||
Type uniqueKeyType,
|
Type uniqueKeyType,
|
||||||
QueryBuildingParameters buildingParameters) {
|
QueryBuildingParameters buildingParameters) {
|
||||||
super( factory );
|
this(
|
||||||
this.entityPersister = entityPersister;
|
entityPersister,
|
||||||
this.uniqueKeyType = uniqueKeyType;
|
factory,
|
||||||
this.entityName = entityPersister.getEntityName();
|
|
||||||
|
|
||||||
this.staticLoadQuery = BatchingLoadQueryDetailsFactory.INSTANCE.makeEntityLoadQueryDetails(
|
|
||||||
entityLoaderQueryDetailsTemplate,
|
entityLoaderQueryDetailsTemplate,
|
||||||
buildingParameters
|
uniqueKeyType,
|
||||||
|
buildingParameters,
|
||||||
|
ResultSetProcessorResolver.DEFAULT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ import org.hibernate.loader.plan.exec.process.spi.CollectionReferenceInitializer
|
||||||
import org.hibernate.loader.plan.exec.process.spi.EntityReferenceInitializer;
|
import org.hibernate.loader.plan.exec.process.spi.EntityReferenceInitializer;
|
||||||
import org.hibernate.loader.plan.exec.process.spi.ReaderCollector;
|
import org.hibernate.loader.plan.exec.process.spi.ReaderCollector;
|
||||||
import org.hibernate.loader.plan.exec.process.spi.ResultSetProcessor;
|
import org.hibernate.loader.plan.exec.process.spi.ResultSetProcessor;
|
||||||
|
import org.hibernate.loader.plan.exec.process.spi.ResultSetProcessorResolver;
|
||||||
import org.hibernate.loader.plan.exec.query.internal.SelectStatementBuilder;
|
import org.hibernate.loader.plan.exec.query.internal.SelectStatementBuilder;
|
||||||
import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters;
|
import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters;
|
||||||
import org.hibernate.loader.plan.exec.spi.AliasResolutionContext;
|
import org.hibernate.loader.plan.exec.spi.AliasResolutionContext;
|
||||||
|
@ -104,6 +105,10 @@ public abstract class AbstractLoadQueryDetails implements LoadQueryDetails {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected void generate() {
|
protected void generate() {
|
||||||
|
generate( ResultSetProcessorResolver.DEFAULT );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void generate(ResultSetProcessorResolver resultSetProcessorResolver) {
|
||||||
// There are 2 high-level requirements to perform here:
|
// There are 2 high-level requirements to perform here:
|
||||||
// 1) Determine the SQL required to carry out the given LoadPlan (and fulfill
|
// 1) Determine the SQL required to carry out the given LoadPlan (and fulfill
|
||||||
// {@code LoadQueryDetails#getSqlStatement()}). SelectStatementBuilder collects the ongoing efforts to
|
// {@code LoadQueryDetails#getSqlStatement()}). SelectStatementBuilder collects the ongoing efforts to
|
||||||
|
@ -190,10 +195,10 @@ public abstract class AbstractLoadQueryDetails implements LoadQueryDetails {
|
||||||
LoadPlanTreePrinter.INSTANCE.logTree( loadPlan, queryProcessor.getAliasResolutionContext() );
|
LoadPlanTreePrinter.INSTANCE.logTree( loadPlan, queryProcessor.getAliasResolutionContext() );
|
||||||
|
|
||||||
this.sqlStatement = select.toStatementString();
|
this.sqlStatement = select.toStatementString();
|
||||||
this.resultSetProcessor = new ResultSetProcessorImpl(
|
this.resultSetProcessor = resultSetProcessorResolver.resolveResultSetProcessor(
|
||||||
loadPlan,
|
loadPlan,
|
||||||
queryProcessor.getAliasResolutionContext(),
|
queryProcessor.getAliasResolutionContext(),
|
||||||
getReaderCollector().buildRowReader(),
|
getReaderCollector(),
|
||||||
shouldUseOptionalEntityInstance(),
|
shouldUseOptionalEntityInstance(),
|
||||||
isSubselectLoadingEnabled( fetchStats )
|
isSubselectLoadingEnabled( fetchStats )
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
package org.hibernate.loader.plan.exec.internal;
|
package org.hibernate.loader.plan.exec.internal;
|
||||||
|
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
|
import org.hibernate.loader.plan.exec.process.spi.ResultSetProcessorResolver;
|
||||||
import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters;
|
import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters;
|
||||||
import org.hibernate.loader.plan.exec.spi.LoadQueryDetails;
|
import org.hibernate.loader.plan.exec.spi.LoadQueryDetails;
|
||||||
import org.hibernate.loader.plan.spi.CollectionReturn;
|
import org.hibernate.loader.plan.spi.CollectionReturn;
|
||||||
|
@ -38,6 +39,7 @@ public class BatchingLoadQueryDetailsFactory {
|
||||||
* @param buildingParameters Any influencers that would affect the generated SQL (mostly we are concerned with those
|
* @param buildingParameters Any influencers that would affect the generated SQL (mostly we are concerned with those
|
||||||
* that add additional joins here)
|
* that add additional joins here)
|
||||||
* @param factory The SessionFactory
|
* @param factory The SessionFactory
|
||||||
|
* @oaram resultSetProcessorResolver The ResultSet processor resolver.
|
||||||
*
|
*
|
||||||
* @return The EntityLoadQueryDetails
|
* @return The EntityLoadQueryDetails
|
||||||
*/
|
*/
|
||||||
|
@ -45,7 +47,8 @@ public class BatchingLoadQueryDetailsFactory {
|
||||||
LoadPlan loadPlan,
|
LoadPlan loadPlan,
|
||||||
String[] keyColumnNames,
|
String[] keyColumnNames,
|
||||||
QueryBuildingParameters buildingParameters,
|
QueryBuildingParameters buildingParameters,
|
||||||
SessionFactoryImplementor factory) {
|
SessionFactoryImplementor factory,
|
||||||
|
ResultSetProcessorResolver resultSetProcessorResolver) {
|
||||||
|
|
||||||
// TODO: how should shouldUseOptionalEntityInformation be used?
|
// TODO: how should shouldUseOptionalEntityInformation be used?
|
||||||
// final int batchSize = buildingParameters.getBatchSize();
|
// final int batchSize = buildingParameters.getBatchSize();
|
||||||
|
@ -64,7 +67,54 @@ public class BatchingLoadQueryDetailsFactory {
|
||||||
aliasResolutionContext,
|
aliasResolutionContext,
|
||||||
rootReturn,
|
rootReturn,
|
||||||
buildingParameters,
|
buildingParameters,
|
||||||
factory
|
factory,
|
||||||
|
resultSetProcessorResolver
|
||||||
|
);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Returns an EntityLoadQueryDetails object from the given inputs.
|
||||||
|
*
|
||||||
|
* @param loadPlan The load plan
|
||||||
|
* @param keyColumnNames The columns to load the entity by (the PK columns or some other unique set of columns)
|
||||||
|
* @param buildingParameters Any influencers that would affect the generated SQL (mostly we are concerned with those
|
||||||
|
* that add additional joins here)
|
||||||
|
* @param factory The SessionFactory
|
||||||
|
*
|
||||||
|
* @return The EntityLoadQueryDetails
|
||||||
|
*/
|
||||||
|
public EntityLoadQueryDetails makeEntityLoadQueryDetails(
|
||||||
|
LoadPlan loadPlan,
|
||||||
|
String[] keyColumnNames,
|
||||||
|
QueryBuildingParameters buildingParameters,
|
||||||
|
SessionFactoryImplementor factory) {
|
||||||
|
|
||||||
|
return makeEntityLoadQueryDetails(
|
||||||
|
loadPlan,
|
||||||
|
keyColumnNames,
|
||||||
|
buildingParameters,
|
||||||
|
factory,
|
||||||
|
ResultSetProcessorResolver.DEFAULT
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a EntityLoadQueryDetails object based on an existing one and additional elements specific to this one.
|
||||||
|
*
|
||||||
|
* @param entityLoadQueryDetailsTemplate the template
|
||||||
|
* @param buildingParameters Any influencers that would affect the generated SQL (mostly we are concerned with those
|
||||||
|
* that add additional joins here)
|
||||||
|
* @oaram resultSetProcessorResolver The ResultSet processor resolver.
|
||||||
|
*
|
||||||
|
* @return The EntityLoadQueryDetails
|
||||||
|
*/
|
||||||
|
public EntityLoadQueryDetails makeEntityLoadQueryDetails(
|
||||||
|
EntityLoadQueryDetails entityLoadQueryDetailsTemplate,
|
||||||
|
QueryBuildingParameters buildingParameters,
|
||||||
|
ResultSetProcessorResolver resultSetProcessorResolver) {
|
||||||
|
return new EntityLoadQueryDetails(
|
||||||
|
entityLoadQueryDetailsTemplate,
|
||||||
|
buildingParameters,
|
||||||
|
resultSetProcessorResolver
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,9 +129,10 @@ public class BatchingLoadQueryDetailsFactory {
|
||||||
public EntityLoadQueryDetails makeEntityLoadQueryDetails(
|
public EntityLoadQueryDetails makeEntityLoadQueryDetails(
|
||||||
EntityLoadQueryDetails entityLoadQueryDetailsTemplate,
|
EntityLoadQueryDetails entityLoadQueryDetailsTemplate,
|
||||||
QueryBuildingParameters buildingParameters) {
|
QueryBuildingParameters buildingParameters) {
|
||||||
return new EntityLoadQueryDetails(
|
return makeEntityLoadQueryDetails(
|
||||||
entityLoadQueryDetailsTemplate,
|
entityLoadQueryDetailsTemplate,
|
||||||
buildingParameters
|
buildingParameters,
|
||||||
|
ResultSetProcessorResolver.DEFAULT
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import org.hibernate.loader.plan.exec.process.internal.ResultSetProcessingContex
|
||||||
import org.hibernate.loader.plan.exec.process.spi.EntityReferenceInitializer;
|
import org.hibernate.loader.plan.exec.process.spi.EntityReferenceInitializer;
|
||||||
import org.hibernate.loader.plan.exec.process.spi.ReaderCollector;
|
import org.hibernate.loader.plan.exec.process.spi.ReaderCollector;
|
||||||
import org.hibernate.loader.plan.exec.process.spi.ResultSetProcessingContext;
|
import org.hibernate.loader.plan.exec.process.spi.ResultSetProcessingContext;
|
||||||
|
import org.hibernate.loader.plan.exec.process.spi.ResultSetProcessorResolver;
|
||||||
import org.hibernate.loader.plan.exec.process.spi.RowReader;
|
import org.hibernate.loader.plan.exec.process.spi.RowReader;
|
||||||
import org.hibernate.loader.plan.exec.query.internal.SelectStatementBuilder;
|
import org.hibernate.loader.plan.exec.query.internal.SelectStatementBuilder;
|
||||||
import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters;
|
import org.hibernate.loader.plan.exec.query.spi.QueryBuildingParameters;
|
||||||
|
@ -58,6 +59,7 @@ public class EntityLoadQueryDetails extends AbstractLoadQueryDetails {
|
||||||
* @param buildingParameters Any influencers that would affect the generated SQL (mostly we are concerned with those
|
* @param buildingParameters Any influencers that would affect the generated SQL (mostly we are concerned with those
|
||||||
* that add additional joins here)
|
* that add additional joins here)
|
||||||
* @param factory The SessionFactory
|
* @param factory The SessionFactory
|
||||||
|
* @param resultSetProcessorResolver The ResultSet resolver.
|
||||||
*/
|
*/
|
||||||
protected EntityLoadQueryDetails(
|
protected EntityLoadQueryDetails(
|
||||||
LoadPlan loadPlan,
|
LoadPlan loadPlan,
|
||||||
|
@ -65,7 +67,9 @@ public class EntityLoadQueryDetails extends AbstractLoadQueryDetails {
|
||||||
AliasResolutionContextImpl aliasResolutionContext,
|
AliasResolutionContextImpl aliasResolutionContext,
|
||||||
EntityReturn rootReturn,
|
EntityReturn rootReturn,
|
||||||
QueryBuildingParameters buildingParameters,
|
QueryBuildingParameters buildingParameters,
|
||||||
SessionFactoryImplementor factory) {
|
SessionFactoryImplementor factory,
|
||||||
|
ResultSetProcessorResolver resultSetProcessorResolver) {
|
||||||
|
|
||||||
super(
|
super(
|
||||||
loadPlan,
|
loadPlan,
|
||||||
aliasResolutionContext,
|
aliasResolutionContext,
|
||||||
|
@ -82,21 +86,55 @@ public class EntityLoadQueryDetails extends AbstractLoadQueryDetails {
|
||||||
new EntityReturnReader( rootReturn ),
|
new EntityReturnReader( rootReturn ),
|
||||||
new EntityReferenceInitializerImpl( rootReturn, entityReferenceAliases, true )
|
new EntityReferenceInitializerImpl( rootReturn, entityReferenceAliases, true )
|
||||||
);
|
);
|
||||||
generate();
|
generate( resultSetProcessorResolver );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a EntityLoadQueryDetails object from the given inputs.
|
||||||
|
*
|
||||||
|
* @param loadPlan The load plan
|
||||||
|
* @param keyColumnNames The columns to load the entity by (the PK columns or some other unique set of columns)
|
||||||
|
* @param buildingParameters Any influencers that would affect the generated SQL (mostly we are concerned with those
|
||||||
|
* that add additional joins here)
|
||||||
|
* @param factory The SessionFactory
|
||||||
|
*/
|
||||||
|
protected EntityLoadQueryDetails(
|
||||||
|
LoadPlan loadPlan,
|
||||||
|
String[] keyColumnNames,
|
||||||
|
AliasResolutionContextImpl aliasResolutionContext,
|
||||||
|
EntityReturn rootReturn,
|
||||||
|
QueryBuildingParameters buildingParameters,
|
||||||
|
SessionFactoryImplementor factory) {
|
||||||
|
this(
|
||||||
|
loadPlan,
|
||||||
|
keyColumnNames,
|
||||||
|
aliasResolutionContext,
|
||||||
|
rootReturn,
|
||||||
|
buildingParameters,
|
||||||
|
factory,
|
||||||
|
ResultSetProcessorResolver.DEFAULT
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected EntityLoadQueryDetails(
|
protected EntityLoadQueryDetails(
|
||||||
EntityLoadQueryDetails initialEntityLoadQueryDetails,
|
EntityLoadQueryDetails initialEntityLoadQueryDetails,
|
||||||
QueryBuildingParameters buildingParameters) {
|
QueryBuildingParameters buildingParameters,
|
||||||
|
ResultSetProcessorResolver resultSetProcessorResolver) {
|
||||||
this(
|
this(
|
||||||
initialEntityLoadQueryDetails.getLoadPlan(),
|
initialEntityLoadQueryDetails.getLoadPlan(),
|
||||||
initialEntityLoadQueryDetails.getKeyColumnNames(),
|
initialEntityLoadQueryDetails.getKeyColumnNames(),
|
||||||
new AliasResolutionContextImpl( initialEntityLoadQueryDetails.getSessionFactory() ),
|
new AliasResolutionContextImpl( initialEntityLoadQueryDetails.getSessionFactory() ),
|
||||||
(EntityReturn) initialEntityLoadQueryDetails.getRootReturn(),
|
(EntityReturn) initialEntityLoadQueryDetails.getRootReturn(),
|
||||||
buildingParameters,
|
buildingParameters,
|
||||||
initialEntityLoadQueryDetails.getSessionFactory()
|
initialEntityLoadQueryDetails.getSessionFactory(),
|
||||||
|
resultSetProcessorResolver
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
protected EntityLoadQueryDetails(
|
||||||
|
EntityLoadQueryDetails initialEntityLoadQueryDetails,
|
||||||
|
QueryBuildingParameters buildingParameters) {
|
||||||
|
this( initialEntityLoadQueryDetails, buildingParameters, ResultSetProcessorResolver.DEFAULT );
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasCollectionInitializers() {
|
public boolean hasCollectionInitializers() {
|
||||||
return CollectionHelper.isNotEmpty( readerCollector.getArrayReferenceInitializers() ) ||
|
return CollectionHelper.isNotEmpty( readerCollector.getArrayReferenceInitializers() ) ||
|
||||||
|
|
|
@ -224,7 +224,7 @@ public abstract class AbstractRowReader implements RowReader {
|
||||||
postLoad( postLoadEvent, context, hydratedEntityRegistrations, afterLoadActionList );
|
postLoad( postLoadEvent, context, hydratedEntityRegistrations, afterLoadActionList );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finishLoadingArrays(ResultSetProcessingContextImpl context) {
|
protected void finishLoadingArrays(ResultSetProcessingContextImpl context) {
|
||||||
for ( CollectionReferenceInitializer arrayReferenceInitializer : arrayReferenceInitializers ) {
|
for ( CollectionReferenceInitializer arrayReferenceInitializer : arrayReferenceInitializers ) {
|
||||||
arrayReferenceInitializer.endLoading( context );
|
arrayReferenceInitializer.endLoading( context );
|
||||||
}
|
}
|
||||||
|
@ -262,13 +262,13 @@ public abstract class AbstractRowReader implements RowReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finishLoadingCollections(ResultSetProcessingContextImpl context) {
|
protected void finishLoadingCollections(ResultSetProcessingContextImpl context) {
|
||||||
for ( CollectionReferenceInitializer collectionReferenceInitializer : collectionReferenceInitializers ) {
|
for ( CollectionReferenceInitializer collectionReferenceInitializer : collectionReferenceInitializers ) {
|
||||||
collectionReferenceInitializer.endLoading( context );
|
collectionReferenceInitializer.endLoading( context );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void afterInitialize(ResultSetProcessingContextImpl context,
|
protected void afterInitialize(ResultSetProcessingContextImpl context,
|
||||||
List<HydratedEntityRegistration> hydratedEntityRegistrations) {
|
List<HydratedEntityRegistration> hydratedEntityRegistrations) {
|
||||||
if ( hydratedEntityRegistrations == null ) {
|
if ( hydratedEntityRegistrations == null ) {
|
||||||
return;
|
return;
|
||||||
|
@ -279,7 +279,7 @@ public abstract class AbstractRowReader implements RowReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void postLoad(
|
protected void postLoad(
|
||||||
PostLoadEvent postLoadEvent,
|
PostLoadEvent postLoadEvent,
|
||||||
ResultSetProcessingContextImpl context,
|
ResultSetProcessingContextImpl context,
|
||||||
List<HydratedEntityRegistration> hydratedEntityRegistrations,
|
List<HydratedEntityRegistration> hydratedEntityRegistrations,
|
||||||
|
|
|
@ -315,10 +315,7 @@ public class ResultSetProcessingContextImpl implements ResultSetProcessingContex
|
||||||
return hydratedEntityRegistrationList;
|
return hydratedEntityRegistrationList;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void wrapUp() {
|
||||||
* Package-protected
|
|
||||||
*/
|
|
||||||
void wrapUp() {
|
|
||||||
createSubselects();
|
createSubselects();
|
||||||
|
|
||||||
if ( hydratedEntityRegistrationList != null ) {
|
if ( hydratedEntityRegistrationList != null ) {
|
||||||
|
|
|
@ -80,11 +80,57 @@ public class ResultSetProcessorImpl implements ResultSetProcessor {
|
||||||
ResultTransformer forcedResultTransformer,
|
ResultTransformer forcedResultTransformer,
|
||||||
List<AfterLoadAction> afterLoadActionList) throws SQLException {
|
List<AfterLoadAction> afterLoadActionList) throws SQLException {
|
||||||
|
|
||||||
handlePotentiallyEmptyCollectionRootReturns( loadPlan, queryParameters.getCollectionKeys(), resultSet, session );
|
handlePotentiallyEmptyCollectionRootReturns( queryParameters.getCollectionKeys(), resultSet, session );
|
||||||
|
|
||||||
|
final ResultSetProcessingContextImpl context = createResultSetProcessingContext(
|
||||||
|
resultSet,
|
||||||
|
session,
|
||||||
|
queryParameters,
|
||||||
|
namedParameterContext,
|
||||||
|
returnProxies,
|
||||||
|
readOnly
|
||||||
|
);
|
||||||
|
|
||||||
|
final List loadResults = extractRows( resultSet, queryParameters, context );
|
||||||
|
|
||||||
|
rowReader.finishUp( context, afterLoadActionList );
|
||||||
|
context.wrapUp();
|
||||||
|
|
||||||
|
session.getPersistenceContextInternal().initializeNonLazyCollections();
|
||||||
|
|
||||||
|
return loadResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ResultSetProcessingContextImpl createResultSetProcessingContext(
|
||||||
|
ResultSet resultSet,
|
||||||
|
final SharedSessionContractImplementor session,
|
||||||
|
QueryParameters queryParameters,
|
||||||
|
NamedParameterContext namedParameterContext,
|
||||||
|
boolean returnProxies,
|
||||||
|
boolean readOnly) {
|
||||||
|
return new ResultSetProcessingContextImpl(
|
||||||
|
resultSet,
|
||||||
|
session,
|
||||||
|
loadPlan,
|
||||||
|
aliasResolutionContext,
|
||||||
|
readOnly,
|
||||||
|
shouldUseOptionalEntityInstance,
|
||||||
|
returnProxies,
|
||||||
|
queryParameters,
|
||||||
|
namedParameterContext,
|
||||||
|
hadSubselectFetches
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<Object> extractRows(
|
||||||
|
ResultSet resultSet,
|
||||||
|
QueryParameters queryParameters,
|
||||||
|
final ResultSetProcessingContextImpl context) throws SQLException {
|
||||||
|
|
||||||
final boolean traceEnabled = LOG.isTraceEnabled();
|
final boolean traceEnabled = LOG.isTraceEnabled();
|
||||||
final int maxRows;
|
final int maxRows;
|
||||||
final List loadResults;
|
final List<Object> loadResults;
|
||||||
|
|
||||||
final RowSelection selection = queryParameters.getRowSelection();
|
final RowSelection selection = queryParameters.getRowSelection();
|
||||||
if ( LimitHelper.hasMaxRows( selection ) ) {
|
if ( LimitHelper.hasMaxRows( selection ) ) {
|
||||||
maxRows = selection.getMaxRows();
|
maxRows = selection.getMaxRows();
|
||||||
|
@ -99,19 +145,6 @@ public class ResultSetProcessorImpl implements ResultSetProcessor {
|
||||||
maxRows = Integer.MAX_VALUE;
|
maxRows = Integer.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
final ResultSetProcessingContextImpl context = new ResultSetProcessingContextImpl(
|
|
||||||
resultSet,
|
|
||||||
session,
|
|
||||||
loadPlan,
|
|
||||||
aliasResolutionContext,
|
|
||||||
readOnly,
|
|
||||||
shouldUseOptionalEntityInstance,
|
|
||||||
returnProxies,
|
|
||||||
queryParameters,
|
|
||||||
namedParameterContext,
|
|
||||||
hadSubselectFetches
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( traceEnabled ) {
|
if ( traceEnabled ) {
|
||||||
LOG.trace( "Processing result set" );
|
LOG.trace( "Processing result set" );
|
||||||
}
|
}
|
||||||
|
@ -134,17 +167,10 @@ public class ResultSetProcessorImpl implements ResultSetProcessor {
|
||||||
LOG.tracev( "Done processing result set ({0} rows)", count );
|
LOG.tracev( "Done processing result set ({0} rows)", count );
|
||||||
}
|
}
|
||||||
|
|
||||||
rowReader.finishUp( context, afterLoadActionList );
|
|
||||||
context.wrapUp();
|
|
||||||
|
|
||||||
session.getPersistenceContextInternal().initializeNonLazyCollections();
|
|
||||||
|
|
||||||
return loadResults;
|
return loadResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void handlePotentiallyEmptyCollectionRootReturns(
|
||||||
private void handlePotentiallyEmptyCollectionRootReturns(
|
|
||||||
LoadPlan loadPlan,
|
|
||||||
Serializable[] collectionKeys,
|
Serializable[] collectionKeys,
|
||||||
ResultSet resultSet,
|
ResultSet resultSet,
|
||||||
SharedSessionContractImplementor session) {
|
SharedSessionContractImplementor session) {
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.loader.plan.exec.process.spi;
|
||||||
|
|
||||||
|
import org.hibernate.loader.plan.exec.process.internal.ResultSetProcessorImpl;
|
||||||
|
import org.hibernate.loader.plan.exec.spi.AliasResolutionContext;
|
||||||
|
import org.hibernate.loader.plan.spi.LoadPlan;
|
||||||
|
|
||||||
|
public interface ResultSetProcessorResolver {
|
||||||
|
|
||||||
|
ResultSetProcessor resolveResultSetProcessor(
|
||||||
|
LoadPlan loadPlan,
|
||||||
|
AliasResolutionContext aliasResolutionContext,
|
||||||
|
ReaderCollector readerCollector,
|
||||||
|
boolean shouldUseOptionalEntityInstance,
|
||||||
|
boolean hadSubselectFetches
|
||||||
|
);
|
||||||
|
|
||||||
|
ResultSetProcessorResolver DEFAULT =
|
||||||
|
(loadPlan, aliasResolutionContext, readerCollector, shouldUseOptionalEntityInstance, hadSubselectFetches) ->
|
||||||
|
new ResultSetProcessorImpl(
|
||||||
|
loadPlan,
|
||||||
|
aliasResolutionContext,
|
||||||
|
readerCollector.buildRowReader(),
|
||||||
|
shouldUseOptionalEntityInstance,
|
||||||
|
hadSubselectFetches
|
||||||
|
);
|
||||||
|
}
|
|
@ -471,6 +471,18 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Would an entity be eagerly loaded given the value provided for {@code overridingEager}?
|
||||||
|
*
|
||||||
|
* @param overridingEager can override eager from the mapping.
|
||||||
|
*
|
||||||
|
* @return If {@code overridingEager} is null, then it does not override.
|
||||||
|
* If true or false then it overrides the mapping value.
|
||||||
|
*/
|
||||||
|
public boolean isEager(Boolean overridingEager) {
|
||||||
|
return overridingEager != null ? overridingEager : this.eager;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getSemiResolvedType(SessionFactoryImplementor factory) {
|
public Type getSemiResolvedType(SessionFactoryImplementor factory) {
|
||||||
return getAssociatedEntityPersister( factory ).getIdentifierType();
|
return getAssociatedEntityPersister( factory ).getIdentifierType();
|
||||||
|
@ -682,12 +694,10 @@ public abstract class EntityType extends AbstractType implements AssociationType
|
||||||
getAssociatedEntityPersister( session.getFactory() )
|
getAssociatedEntityPersister( session.getFactory() )
|
||||||
.isInstrumented();
|
.isInstrumented();
|
||||||
|
|
||||||
boolean eager = overridingEager != null ? overridingEager : this.eager;
|
|
||||||
|
|
||||||
Object proxyOrEntity = session.internalLoad(
|
Object proxyOrEntity = session.internalLoad(
|
||||||
getAssociatedEntityName(),
|
getAssociatedEntityName(),
|
||||||
id,
|
id,
|
||||||
eager,
|
isEager( overridingEager ),
|
||||||
isNullable()
|
isNullable()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue