Search in sources :

Example 1 with MultiLoadOptions

use of org.hibernate.persister.entity.MultiLoadOptions in project hibernate-reactive by hibernate.

the class ReactiveDynamicBatchingEntityLoaderBuilder method performUnorderedMultiLoad.

private CompletionStage<List<Object>> performUnorderedMultiLoad(OuterJoinLoadable persister, Serializable[] ids, SessionImplementor session, MultiLoadOptions loadOptions) {
    assert !loadOptions.isOrderReturnEnabled();
    final List<Object> result = CollectionHelper.arrayList(ids.length);
    final LockOptions lockOptions = loadOptions.getLockOptions() == null ? new LockOptions(LockMode.NONE) : loadOptions.getLockOptions();
    if (loadOptions.isSessionCheckingEnabled() || loadOptions.isSecondLevelCacheCheckingEnabled()) {
        // the user requested that we exclude ids corresponding to already managed
        // entities from the generated load SQL.  So here we will iterate all
        // incoming id values and see whether it corresponds to an existing
        // entity associated with the PC - if it does we add it to the result
        // list immediately and remove its id from the group of ids to load.
        boolean foundAnyManagedEntities = false;
        final List<Serializable> nonManagedIds = new ArrayList<>();
        for (Serializable id : ids) {
            final EntityKey entityKey = new EntityKey(id, persister);
            LoadEvent loadEvent = new LoadEvent(id, persister.getMappedClass().getName(), lockOptions, (EventSource) session, null);
            Object managedEntity = null;
            // look for it in the Session first
            CacheEntityLoaderHelper.PersistenceContextEntry persistenceContextEntry = CacheEntityLoaderHelper.INSTANCE.loadFromSessionCache(loadEvent, entityKey, LoadEventListener.GET);
            if (loadOptions.isSessionCheckingEnabled()) {
                managedEntity = persistenceContextEntry.getEntity();
                if (managedEntity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled() && !persistenceContextEntry.isManaged()) {
                    foundAnyManagedEntities = true;
                    result.add(null);
                    continue;
                }
            }
            if (managedEntity == null && loadOptions.isSecondLevelCacheCheckingEnabled()) {
                managedEntity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache(loadEvent, persister, entityKey);
            }
            if (managedEntity != null) {
                foundAnyManagedEntities = true;
                result.add(managedEntity);
            } else {
                nonManagedIds.add(id);
            }
        }
        if (foundAnyManagedEntities) {
            if (nonManagedIds.isEmpty()) {
                // all of the given ids were already associated with the Session
                return completedFuture(result);
            } else {
                // over-write the ids to be loaded with the collection of
                // just non-managed ones
                ids = nonManagedIds.toArray((Serializable[]) Array.newInstance(ids.getClass().getComponentType(), nonManagedIds.size()));
            }
        }
    }
    int numberOfIdsLeft = ids.length;
    final int maxBatchSize;
    if (loadOptions.getBatchSize() != null && loadOptions.getBatchSize() > 0) {
        maxBatchSize = loadOptions.getBatchSize();
    } else {
        maxBatchSize = session.getJdbcServices().getJdbcEnvironment().getDialect().getDefaultBatchLoadSizingStrategy().determineOptimalBatchLoadSize(persister.getIdentifierType().getColumnSpan(session.getFactory()), numberOfIdsLeft);
    }
    CompletionStage<Void> stage = voidFuture();
    // TODO: Trampoline this!
    int idPosition = 0;
    while (numberOfIdsLeft > 0) {
        int batchSize = Math.min(numberOfIdsLeft, maxBatchSize);
        final ReactiveDynamicBatchingEntityLoader batchingLoader = new ReactiveDynamicBatchingEntityLoader(persister, batchSize, lockOptions, session.getFactory(), session.getLoadQueryInfluencers());
        Serializable[] idsInBatch = new Serializable[batchSize];
        System.arraycopy(ids, idPosition, idsInBatch, 0, batchSize);
        QueryParameters qp = buildMultiLoadQueryParameters(persister, idsInBatch, lockOptions);
        CompletionStage<Void> fetch = batchingLoader.doEntityBatchFetch(session, qp, idsInBatch).thenAccept(result::addAll);
        stage = stage.thenCompose(v -> fetch);
        numberOfIdsLeft = numberOfIdsLeft - batchSize;
        idPosition += batchSize;
    }
    return stage.thenApply(v -> result);
}
Also used : CollectionHelper(org.hibernate.internal.util.collections.CollectionHelper) CacheEntityLoaderHelper(org.hibernate.loader.entity.CacheEntityLoaderHelper) Arrays(java.util.Arrays) CompletionStages.completedFuture(org.hibernate.reactive.util.impl.CompletionStages.completedFuture) Array(java.lang.reflect.Array) EventSource(org.hibernate.event.spi.EventSource) PersistenceContext(org.hibernate.engine.spi.PersistenceContext) UniqueEntityLoader(org.hibernate.loader.entity.UniqueEntityLoader) ArrayList(java.util.ArrayList) MultiLoadOptions(org.hibernate.persister.entity.MultiLoadOptions) Status(org.hibernate.engine.spi.Status) CompletionStages.voidFuture(org.hibernate.reactive.util.impl.CompletionStages.voidFuture) SessionFactoryImplementor(org.hibernate.engine.spi.SessionFactoryImplementor) QueryParameters(org.hibernate.engine.spi.QueryParameters) LockMode(org.hibernate.LockMode) LockOptions(org.hibernate.LockOptions) EntityKey(org.hibernate.engine.spi.EntityKey) Serializable(java.io.Serializable) LoadEventListener(org.hibernate.event.spi.LoadEventListener) LoadQueryInfluencers(org.hibernate.engine.spi.LoadQueryInfluencers) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) OuterJoinLoadable(org.hibernate.persister.entity.OuterJoinLoadable) EntityEntry(org.hibernate.engine.spi.EntityEntry) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) Type(org.hibernate.type.Type) LoadEvent(org.hibernate.event.spi.LoadEvent) Serializable(java.io.Serializable) LockOptions(org.hibernate.LockOptions) LoadEvent(org.hibernate.event.spi.LoadEvent) ArrayList(java.util.ArrayList) QueryParameters(org.hibernate.engine.spi.QueryParameters) CacheEntityLoaderHelper(org.hibernate.loader.entity.CacheEntityLoaderHelper) EntityKey(org.hibernate.engine.spi.EntityKey)

Example 2 with MultiLoadOptions

use of org.hibernate.persister.entity.MultiLoadOptions in project hibernate-reactive by hibernate.

the class ReactiveDynamicBatchingEntityLoaderBuilder method performOrderedMultiLoad.

private CompletionStage<List<Object>> performOrderedMultiLoad(OuterJoinLoadable persister, Serializable[] ids, SessionImplementor session, MultiLoadOptions loadOptions) {
    assert loadOptions.isOrderReturnEnabled();
    final List<Object> result = CollectionHelper.arrayList(ids.length);
    final LockOptions lockOptions = loadOptions.getLockOptions() == null ? new LockOptions(LockMode.NONE) : loadOptions.getLockOptions();
    final int maxBatchSize;
    if (loadOptions.getBatchSize() != null && loadOptions.getBatchSize() > 0) {
        maxBatchSize = loadOptions.getBatchSize();
    } else {
        maxBatchSize = session.getJdbcServices().getJdbcEnvironment().getDialect().getDefaultBatchLoadSizingStrategy().determineOptimalBatchLoadSize(persister.getIdentifierType().getColumnSpan(session.getFactory()), ids.length);
    }
    final List<Serializable> idsInBatch = new ArrayList<>();
    final List<Integer> elementPositionsLoadedByBatch = new ArrayList<>();
    CompletionStage<?> stage = voidFuture();
    // TODO: Trampoline this!
    for (int i = 0; i < ids.length; i++) {
        final Serializable id = ids[i];
        final EntityKey entityKey = new EntityKey(id, persister);
        if (loadOptions.isSessionCheckingEnabled() || loadOptions.isSecondLevelCacheCheckingEnabled()) {
            LoadEvent loadEvent = new LoadEvent(id, persister.getMappedClass().getName(), lockOptions, (EventSource) session, null);
            Object managedEntity = null;
            if (loadOptions.isSessionCheckingEnabled()) {
                // look for it in the Session first
                CacheEntityLoaderHelper.PersistenceContextEntry persistenceContextEntry = CacheEntityLoaderHelper.INSTANCE.loadFromSessionCache(loadEvent, entityKey, LoadEventListener.GET);
                managedEntity = persistenceContextEntry.getEntity();
                if (managedEntity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled() && !persistenceContextEntry.isManaged()) {
                    // put a null in the result
                    result.add(i, null);
                    continue;
                }
            }
            if (managedEntity == null && loadOptions.isSecondLevelCacheCheckingEnabled()) {
                // look for it in the SessionFactory
                managedEntity = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache(loadEvent, persister, entityKey);
            }
            if (managedEntity != null) {
                result.add(i, managedEntity);
                continue;
            }
        }
        // if we did not hit any of the continues above, then we need to batch
        // load the entity state.
        idsInBatch.add(ids[i]);
        if (idsInBatch.size() >= maxBatchSize) {
            CompletionStage<List<Object>> load = performOrderedBatchLoad(idsInBatch, lockOptions, persister, session);
            stage = stage.thenCompose(v -> load);
        }
        // Save the EntityKey instance for use later!
        result.add(i, entityKey);
        elementPositionsLoadedByBatch.add(i);
    }
    if (!idsInBatch.isEmpty()) {
        CompletionStage<List<Object>> load = performOrderedBatchLoad(idsInBatch, lockOptions, persister, session);
        stage = stage.thenCompose(v -> load);
    }
    return stage.thenApply(v -> {
        final PersistenceContext persistenceContext = session.getPersistenceContextInternal();
        for (Integer position : elementPositionsLoadedByBatch) {
            // the element value at this position in the result List should be
            // the EntityKey for that entity; reuse it!
            final EntityKey entityKey = (EntityKey) result.get(position);
            Object entity = persistenceContext.getEntity(entityKey);
            if (entity != null && !loadOptions.isReturnOfDeletedEntitiesEnabled()) {
                // make sure it is not DELETED
                final EntityEntry entry = persistenceContext.getEntry(entity);
                if (entry.getStatus() == Status.DELETED || entry.getStatus() == Status.GONE) {
                    // the entity is locally deleted, and the options ask that we not return such entities...
                    entity = null;
                }
            }
            result.set(position, entity);
        }
        return result;
    });
}
Also used : CollectionHelper(org.hibernate.internal.util.collections.CollectionHelper) CacheEntityLoaderHelper(org.hibernate.loader.entity.CacheEntityLoaderHelper) Arrays(java.util.Arrays) CompletionStages.completedFuture(org.hibernate.reactive.util.impl.CompletionStages.completedFuture) Array(java.lang.reflect.Array) EventSource(org.hibernate.event.spi.EventSource) PersistenceContext(org.hibernate.engine.spi.PersistenceContext) UniqueEntityLoader(org.hibernate.loader.entity.UniqueEntityLoader) ArrayList(java.util.ArrayList) MultiLoadOptions(org.hibernate.persister.entity.MultiLoadOptions) Status(org.hibernate.engine.spi.Status) CompletionStages.voidFuture(org.hibernate.reactive.util.impl.CompletionStages.voidFuture) SessionFactoryImplementor(org.hibernate.engine.spi.SessionFactoryImplementor) QueryParameters(org.hibernate.engine.spi.QueryParameters) LockMode(org.hibernate.LockMode) LockOptions(org.hibernate.LockOptions) EntityKey(org.hibernate.engine.spi.EntityKey) Serializable(java.io.Serializable) LoadEventListener(org.hibernate.event.spi.LoadEventListener) LoadQueryInfluencers(org.hibernate.engine.spi.LoadQueryInfluencers) List(java.util.List) CompletionStage(java.util.concurrent.CompletionStage) OuterJoinLoadable(org.hibernate.persister.entity.OuterJoinLoadable) EntityEntry(org.hibernate.engine.spi.EntityEntry) SessionImplementor(org.hibernate.engine.spi.SessionImplementor) Type(org.hibernate.type.Type) LoadEvent(org.hibernate.event.spi.LoadEvent) Serializable(java.io.Serializable) LockOptions(org.hibernate.LockOptions) LoadEvent(org.hibernate.event.spi.LoadEvent) ArrayList(java.util.ArrayList) PersistenceContext(org.hibernate.engine.spi.PersistenceContext) CacheEntityLoaderHelper(org.hibernate.loader.entity.CacheEntityLoaderHelper) EntityKey(org.hibernate.engine.spi.EntityKey) EntityEntry(org.hibernate.engine.spi.EntityEntry) ArrayList(java.util.ArrayList) List(java.util.List)

Aggregations

Serializable (java.io.Serializable)2 Array (java.lang.reflect.Array)2 ArrayList (java.util.ArrayList)2 Arrays (java.util.Arrays)2 List (java.util.List)2 CompletionStage (java.util.concurrent.CompletionStage)2 LockMode (org.hibernate.LockMode)2 LockOptions (org.hibernate.LockOptions)2 EntityEntry (org.hibernate.engine.spi.EntityEntry)2 EntityKey (org.hibernate.engine.spi.EntityKey)2 LoadQueryInfluencers (org.hibernate.engine.spi.LoadQueryInfluencers)2 PersistenceContext (org.hibernate.engine.spi.PersistenceContext)2 QueryParameters (org.hibernate.engine.spi.QueryParameters)2 SessionFactoryImplementor (org.hibernate.engine.spi.SessionFactoryImplementor)2 SessionImplementor (org.hibernate.engine.spi.SessionImplementor)2 Status (org.hibernate.engine.spi.Status)2 EventSource (org.hibernate.event.spi.EventSource)2 LoadEvent (org.hibernate.event.spi.LoadEvent)2 LoadEventListener (org.hibernate.event.spi.LoadEventListener)2 CollectionHelper (org.hibernate.internal.util.collections.CollectionHelper)2