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);
}
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;
});
}
Aggregations