diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java index fe8ccb561bcd..084658b7d3b7 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiIdEntityLoader.java @@ -92,27 +92,28 @@ private List performUnorderedMultiLoad( assert !loadOptions.isOrderReturnEnabled(); assert ids != null; if ( MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) { - MULTI_KEY_LOAD_LOGGER.tracef( "#performUnorderedMultiLoad(`%s`, ..)", getLoadable().getEntityName() ); + MULTI_KEY_LOAD_LOGGER.tracef( "Unordered MultiLoad starting: " + + getLoadable().getEntityName() ); } - return unorderedMultiLoad( ids, loadOptions, lockOptions( loadOptions ), session ); + return unorderedMultiLoad( ids, loadOptions, session ); } - protected List performOrderedMultiLoad( + private List performOrderedMultiLoad( Object[] ids, MultiIdLoadOptions loadOptions, SharedSessionContractImplementor session) { assert loadOptions.isOrderReturnEnabled(); assert ids != null; if ( MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) { - MULTI_KEY_LOAD_LOGGER.tracef( "#performOrderedMultiLoad(`%s`, ..)", getLoadable().getEntityName() ); + MULTI_KEY_LOAD_LOGGER.tracef( "Ordered MultiLoad starting: " + + getLoadable().getEntityName() ); } - return orderedMultiLoad( ids, loadOptions, lockOptions( loadOptions ), session ); + return orderedMultiLoad( ids, loadOptions, session ); } private List orderedMultiLoad( Object[] ids, MultiIdLoadOptions loadOptions, - LockOptions lockOptions, SharedSessionContractImplementor session) { final boolean idCoercionEnabled = isIdCoercionEnabled(); final JavaType idType = getLoadable().getIdentifierMapping().getJavaType(); @@ -124,6 +125,8 @@ private List orderedMultiLoad( final List idsInBatch = new ArrayList<>(); final List elementPositionsLoadedByBatch = new ArrayList<>(); + final LockOptions lockOptions = lockOptions( loadOptions ); + for ( int i = 0; i < ids.length; i++ ) { final Object id = idCoercionEnabled ? idType.coerce( ids[i], session ) : ids[i]; final EntityKey entityKey = new EntityKey( id, getLoadable().getEntityPersister() ); @@ -158,7 +161,7 @@ private List orderedMultiLoad( return (List) result; } - protected static LockOptions lockOptions(MultiIdLoadOptions loadOptions) { + private static LockOptions lockOptions(MultiIdLoadOptions loadOptions) { return loadOptions.getLockOptions() == null ? new LockOptions( LockMode.NONE ) : loadOptions.getLockOptions(); @@ -166,7 +169,7 @@ protected static LockOptions lockOptions(MultiIdLoadOptions loadOptions) { protected abstract int maxBatchSize(Object[] ids, MultiIdLoadOptions loadOptions); - protected void handleResults( + private void handleResults( MultiIdLoadOptions loadOptions, SharedSessionContractImplementor session, List elementPositionsLoadedByBatch, @@ -199,7 +202,7 @@ protected abstract void loadEntitiesById( MultiIdLoadOptions loadOptions, SharedSessionContractImplementor session); - protected boolean loadFromEnabledCaches( + private boolean loadFromEnabledCaches( MultiIdLoadOptions loadOptions, SharedSessionContractImplementor session, Object id, @@ -250,14 +253,14 @@ private boolean isLoadFromCaches( protected List unorderedMultiLoad( Object[] ids, MultiIdLoadOptions loadOptions, - LockOptions lockOptions, SharedSessionContractImplementor session) { + final LockOptions lockOptions = lockOptions( loadOptions ); final List result = arrayList( ids.length ); final Object[] unresolvableIds = resolveInCachesIfEnabled( ids, loadOptions, lockOptions, session, (position, entityKey, resolvedRef) -> result.add( (T) resolvedRef ) ); if ( !isEmpty( unresolvableIds ) ) { - loadEntitiesWithUnresolvedIds( loadOptions, lockOptions, session, unresolvableIds, result ); + loadEntitiesWithUnresolvedIds( unresolvableIds, loadOptions, lockOptions, result, session ); final BatchFetchQueue batchFetchQueue = session.getPersistenceContextInternal().getBatchFetchQueue(); final EntityPersister persister = getLoadable().getEntityPersister(); for ( Object id : unresolvableIds ) { @@ -273,13 +276,13 @@ protected List unorderedMultiLoad( } protected abstract void loadEntitiesWithUnresolvedIds( + Object[] unresolvableIds, MultiIdLoadOptions loadOptions, LockOptions lockOptions, - SharedSessionContractImplementor session, - Object[] unresolvableIds, - List results); + List results, + SharedSessionContractImplementor session); - protected final Object[] resolveInCachesIfEnabled( + private Object[] resolveInCachesIfEnabled( Object[] ids, @NonNull MultiIdLoadOptions loadOptions, @NonNull LockOptions lockOptions, @@ -296,7 +299,7 @@ protected final Object[] resolveInCachesIfEnabled( : ids; } - protected final Object[] resolveInCaches( + private Object[] resolveInCaches( Object[] ids, MultiIdLoadOptions loadOptions, LockOptions lockOptions, diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiNaturalIdLoader.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiNaturalIdLoader.java index 3cbe665c8184..2fe6010e4f85 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiNaturalIdLoader.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/AbstractMultiNaturalIdLoader.java @@ -13,13 +13,15 @@ import org.hibernate.loader.ast.spi.MultiNaturalIdLoadOptions; import org.hibernate.loader.ast.spi.MultiNaturalIdLoader; import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.metamodel.mapping.NaturalIdMapping; -import java.util.Collections; import java.util.List; +import static java.util.Collections.emptyList; import static org.hibernate.internal.util.collections.CollectionHelper.arrayList; import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty; import static org.hibernate.loader.ast.internal.LoaderHelper.upgradeLock; +import static org.hibernate.loader.ast.internal.MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER; /** * @author Jan Schatteman @@ -27,8 +29,6 @@ public abstract class AbstractMultiNaturalIdLoader implements MultiNaturalIdLoader { private final EntityMappingType entityDescriptor; - protected MultiNaturalIdLoadOptions options; - public AbstractMultiNaturalIdLoader(EntityMappingType entityDescriptor) { this.entityDescriptor = entityDescriptor; } @@ -36,118 +36,129 @@ public AbstractMultiNaturalIdLoader(EntityMappingType entityDescriptor) { @Override public List multiLoad(K[] naturalIds, MultiNaturalIdLoadOptions options, SharedSessionContractImplementor session) { assert naturalIds != null; - - this.options = options; - if ( naturalIds.length == 0 ) { - return Collections.emptyList(); + return emptyList(); + } + else { + return options.isOrderReturnEnabled() + ? performOrderedMultiLoad( naturalIds, options, session ) + : performUnorderedMultiLoad( naturalIds, options, session ); } - - return options.isOrderReturnEnabled() - ? performOrderedMultiLoad( naturalIds, options, session ) - : performUnorderedMultiLoad( naturalIds, options, session ); } - private List performUnorderedMultiLoad(K[] naturalIds, MultiNaturalIdLoadOptions options, SharedSessionContractImplementor session) { - if ( MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) { - MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER.tracef( "Unordered MultiLoad Starting - `%s`", getEntityDescriptor().getEntityName() ); + private List performUnorderedMultiLoad( + K[] naturalIds, + MultiNaturalIdLoadOptions loadOptions, + SharedSessionContractImplementor session) { + if ( MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) { + MULTI_KEY_LOAD_LOGGER.tracef( "Unordered MultiLoad starting: " + + getEntityDescriptor().getEntityName() ); } + return unorderedMultiLoad( naturalIds, loadOptions, session ); + } - return unorderedMultiLoad( - naturalIds, - session, - options.getLockOptions() == null ? LockOptions.NONE : options.getLockOptions() - ); + private static LockOptions lockOptions(MultiNaturalIdLoadOptions loadOptions) { + final LockOptions lockOptions = loadOptions.getLockOptions(); + return lockOptions == null ? LockOptions.NONE : lockOptions; } - protected List unorderedMultiLoad(K[] naturalIds, SharedSessionContractImplementor session, LockOptions lockOptions) { + private List unorderedMultiLoad( + K[] naturalIds, + MultiNaturalIdLoadOptions loadOptions, + SharedSessionContractImplementor session) { final List results = arrayList( naturalIds.length ); + final LockOptions lockOptions = lockOptions( loadOptions ); final Object[] unresolvedIds = - checkPersistenceContextForCachedResults( naturalIds, session, lockOptions, results ); + checkPersistenceContextForCachedResults( naturalIds, loadOptions, session, lockOptions, results ); if ( !isEmpty( unresolvedIds ) ) { - results.addAll( loadEntitiesWithUnresolvedIds(unresolvedIds, session, lockOptions) ); + results.addAll( loadEntitiesWithUnresolvedIds( unresolvedIds, loadOptions, lockOptions, session ) ); } - return results; } - protected abstract List loadEntitiesWithUnresolvedIds(Object[] unresolvedIds, SharedSessionContractImplementor session, LockOptions lockOptions); + protected abstract List loadEntitiesWithUnresolvedIds( + Object[] unresolvedIds, + MultiNaturalIdLoadOptions loadOptions, + LockOptions lockOptions, + SharedSessionContractImplementor session); private List performOrderedMultiLoad(K[] naturalIds, MultiNaturalIdLoadOptions options, SharedSessionContractImplementor session) { - if ( MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) { - MultiKeyLoadLogging.MULTI_KEY_LOAD_LOGGER.tracef( "Ordered MultiLoad Starting - `%s`", getEntityDescriptor().getEntityName() ); + if ( MULTI_KEY_LOAD_LOGGER.isTraceEnabled() ) { + MULTI_KEY_LOAD_LOGGER.trace( "Ordered MultiLoad starting: " + + getEntityDescriptor().getEntityName() ); } - - return orderedMultiLoad( - naturalIds, - session, - options.getLockOptions() == null ? LockOptions.NONE : options.getLockOptions() - ); + return orderedMultiLoad( naturalIds, options, session ); } - protected List orderedMultiLoad( K[] naturalIds, SharedSessionContractImplementor session, LockOptions lockOptions ) { - - unorderedMultiLoad( naturalIds, session, lockOptions ); - - return sortResults( naturalIds, session, lockOptions ); + private List orderedMultiLoad( + K[] naturalIds, + MultiNaturalIdLoadOptions loadOptions, + SharedSessionContractImplementor session) { + unorderedMultiLoad( naturalIds, loadOptions, session ); + return sortResults( naturalIds, loadOptions, session ); } - protected List sortResults( K[] naturalIds, SharedSessionContractImplementor session, LockOptions lockOptions ) { - List results = arrayList(naturalIds.length); - for ( int i = 0; i < naturalIds.length; i++ ) { - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - - Object id = persistenceContext.getNaturalIdResolutions().findCachedIdByNaturalId( naturalIds[i], getEntityDescriptor() ); - - // Id can be null if a non-existent natural id is requested - Object entity = (id == null) ? null : persistenceContext.getEntity( new EntityKey( id, getEntityDescriptor().getEntityPersister() ) ); - if ( entity != null && !options.isReturnOfDeletedEntitiesEnabled() ) { - // make sure it is not DELETED - final EntityEntry entry = persistenceContext.getEntry( entity ); - if ( entry.getStatus().isDeletedOrGone() ) { - // the entity is locally deleted, and the options ask that we not return such entities... - entity = null; - } - else { - entity = persistenceContext.proxyFor( entity ); - } + private List sortResults( + K[] naturalIds, + MultiNaturalIdLoadOptions loadOptions, + SharedSessionContractImplementor session) { + final PersistenceContext context = session.getPersistenceContextInternal(); + final List results = arrayList( naturalIds.length ); + for ( K naturalId : naturalIds ) { + final Object entity = entityForNaturalId( context, naturalId ); + final Object result; + if ( entity == null + // the entity is locally deleted, and the options ask that we not return such entities + || !loadOptions.isReturnOfDeletedEntitiesEnabled() + && context.getEntry( entity ).getStatus().isDeletedOrGone() ) { + result = null; } - results.add( (E) entity ); + else { + result = context.proxyFor( entity ); + } + results.add( (E) result ); } - return results; } - private Object[] checkPersistenceContextForCachedResults( K[] naturalIds, SharedSessionContractImplementor session, LockOptions lockOptions, List results ) { - List unresolvedIds = arrayList(naturalIds.length); - - final PersistenceContext persistenceContext = session.getPersistenceContextInternal(); - for ( int i = 0; i < naturalIds.length; i++ ) { - - final Object normalizedNaturalId = getEntityDescriptor().getNaturalIdMapping().normalizeInput( naturalIds[i] ); - Object id = persistenceContext.getNaturalIdResolutions().findCachedIdByNaturalId( normalizedNaturalId, getEntityDescriptor() ); - - // Id can be null if a non-existent natural id is requested, or a mutable natural id was changed and then deleted - Object entity = id == null ? null : persistenceContext.getEntity( new EntityKey( id, getEntityDescriptor().getEntityPersister() ) ); + private Object entityForNaturalId(PersistenceContext context, K naturalId) { + final EntityMappingType descriptor = getEntityDescriptor(); + final Object id = context.getNaturalIdResolutions().findCachedIdByNaturalId( naturalId, descriptor ); + // id can be null if a non-existent natural id is requested, or a mutable natural id was changed and then deleted + return id == null ? null : context.getEntity( new EntityKey( id, descriptor.getEntityPersister() ) ); + } + private Object[] checkPersistenceContextForCachedResults( + K[] naturalIds, + MultiNaturalIdLoadOptions loadOptions, + SharedSessionContractImplementor session, + LockOptions lockOptions, + List results ) { + final List unresolvedIds = arrayList( naturalIds.length ); + final PersistenceContext context = session.getPersistenceContextInternal(); + final NaturalIdMapping naturalIdMapping = getEntityDescriptor().getNaturalIdMapping(); + for ( K naturalId : naturalIds ) { + final Object entity = entityForNaturalId( context, naturalIdMapping.normalizeInput( naturalId ) ); if ( entity != null ) { // Entity is already in the persistence context - final EntityEntry entry = persistenceContext.getEntry( entity ); - // either a managed entry, or a deleted one with returnDeleted enabled - if ( !entry.getStatus().isDeletedOrGone() || options.isReturnOfDeletedEntitiesEnabled() ) { - results.add( (E) persistenceContext.proxyFor(entity) ); - upgradeLock( entity, entry, lockOptions, session.getSession().asEventSource() ); + final EntityEntry entry = context.getEntry( entity ); + if ( loadOptions.isReturnOfDeletedEntitiesEnabled() + || !entry.getStatus().isDeletedOrGone() ) { + // either a managed entry, or a deleted one with returnDeleted enabled + upgradeLock( entity, entry, lockOptions, session ); + final Object result = context.proxyFor( entity ); + results.add( (E) result ); } } else { - // entity either doesn't exist or hasn't been loaded in the PC yet, in both cases we add the natural id - // to the ids that still need to be recovered, in case the id corresponds to a non-existent - // instance nothing will be in the results for it, which is ok in unordered multiload - unresolvedIds.add(naturalIds[i]); + // entity either doesn't exist or hasn't been loaded in the PC yet, in both cases we add + // the natural id to the ids that still need to be recovered, in case the id corresponds + // to a nonexistent instance nothing will be in the results for it, which is ok in + // unordered multiload + unresolvedIds.add( naturalId ); } } - - return unresolvedIds.toArray( new Object[0] ); + return unresolvedIds.toArray(); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java index 04d1c2952a78..4ed2874b71e4 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderArrayParam.java @@ -126,11 +126,11 @@ public LockOptions getLockOptions() { @Override protected void loadEntitiesWithUnresolvedIds( + Object[] unresolvableIds, MultiIdLoadOptions loadOptions, LockOptions lockOptions, - SharedSessionContractImplementor session, - Object[] unresolvableIds, - List result) { + List result, + SharedSessionContractImplementor session) { final SelectStatement sqlAst = createSelectBySingleArrayParameter( getLoadable(), getIdentifierMapping(), diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderInPredicate.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderInPredicate.java index 0a01d0b25596..cf3a3272f6cf 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderInPredicate.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiIdEntityLoaderInPredicate.java @@ -174,11 +174,11 @@ private List performSingleMultiLoad(Object id, LockOptions lockOptions, Share @Override protected void loadEntitiesWithUnresolvedIds( + Object[] unresolvableIds, MultiIdLoadOptions loadOptions, LockOptions lockOptions, - SharedSessionContractImplementor session, - Object[] unresolvableIds, - List result) { + List result, + SharedSessionContractImplementor session) { final int maxBatchSize = maxBatchSize( unresolvableIds, loadOptions ); int numberOfIdsLeft = unresolvableIds.length; int idPosition = 0; diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java index 25364be9b859..c7ca5b591709 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderArrayParam.java @@ -9,6 +9,7 @@ import org.hibernate.LockOptions; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.loader.ast.spi.MultiNaturalIdLoadOptions; import org.hibernate.loader.ast.spi.SqlArrayMultiKeyLoader; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.JdbcMapping; @@ -44,7 +45,11 @@ protected BasicAttributeMapping getNaturalIdAttribute() { } @Override - public List loadEntitiesWithUnresolvedIds(Object[] naturalIds, SharedSessionContractImplementor session, LockOptions lockOptions) { + public List loadEntitiesWithUnresolvedIds( + Object[] naturalIds, + MultiNaturalIdLoadOptions loadOptions, + LockOptions lockOptions, + SharedSessionContractImplementor session) { final SessionFactoryImplementor sessionFactory = session.getFactory(); diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderInPredicate.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderInPredicate.java index cdf2e9e07c3b..2bbc1f6eb933 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderInPredicate.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/MultiNaturalIdLoaderInPredicate.java @@ -9,6 +9,7 @@ import org.hibernate.LockOptions; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; +import org.hibernate.loader.ast.spi.MultiNaturalIdLoadOptions; import org.hibernate.loader.ast.spi.SqlInPredicateMultiKeyLoader; import org.hibernate.metamodel.mapping.EntityMappingType; @@ -22,13 +23,17 @@ public MultiNaturalIdLoaderInPredicate(EntityMappingType entityDescriptor) { } @Override - public List loadEntitiesWithUnresolvedIds(Object[] naturalIds, SharedSessionContractImplementor session, LockOptions lockOptions) { + public List loadEntitiesWithUnresolvedIds( + Object[] naturalIds, + MultiNaturalIdLoadOptions loadOptions, + LockOptions lockOptions, + SharedSessionContractImplementor session) { final SessionFactoryImplementor sessionFactory = session.getFactory(); final int maxBatchSize; - if ( options.getBatchSize() != null && options.getBatchSize() > 0 ) { - maxBatchSize = options.getBatchSize(); + if ( loadOptions.getBatchSize() != null && loadOptions.getBatchSize() > 0 ) { + maxBatchSize = loadOptions.getBatchSize(); } else { maxBatchSize =