HHH-17948 make findAll() accept FindOptions
and add missing options to MultiIdentifierLoadAccess
This commit is contained in:
parent
62e1b0470e
commit
6e2ed7f1a0
|
@ -51,6 +51,15 @@ public interface MultiIdentifierLoadAccess<T> {
|
|||
*/
|
||||
MultiIdentifierLoadAccess<T> with(CacheMode cacheMode);
|
||||
|
||||
/**
|
||||
* Specify whether the entities should be loaded in read-only mode.
|
||||
*
|
||||
* @see Session#setDefaultReadOnly(boolean)
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
MultiIdentifierLoadAccess<T> withReadOnly(boolean readOnly);
|
||||
|
||||
/**
|
||||
* Override the associations fetched by default by specifying
|
||||
* the complete list of associations to be fetched as an
|
||||
|
@ -88,6 +97,30 @@ public interface MultiIdentifierLoadAccess<T> {
|
|||
*/
|
||||
MultiIdentifierLoadAccess<T> with(RootGraph<T> graph, GraphSemantic semantic);
|
||||
|
||||
/**
|
||||
* Customize the associations fetched by specifying a
|
||||
* {@linkplain org.hibernate.annotations.FetchProfile fetch profile}
|
||||
* that should be enabled during this operation.
|
||||
* <p>
|
||||
* This allows the {@linkplain Session#isFetchProfileEnabled(String)
|
||||
* session-level fetch profiles} to be temporarily overridden.
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
MultiIdentifierLoadAccess<T> enableFetchProfile(String profileName);
|
||||
|
||||
/**
|
||||
* Customize the associations fetched by specifying a
|
||||
* {@linkplain org.hibernate.annotations.FetchProfile fetch profile}
|
||||
* that should be disabled during this operation.
|
||||
* <p>
|
||||
* This allows the {@linkplain Session#isFetchProfileEnabled(String)
|
||||
* session-level fetch profiles} to be temporarily overridden.
|
||||
*
|
||||
* @since 7.0
|
||||
*/
|
||||
MultiIdentifierLoadAccess<T> disableFetchProfile(String profileName);
|
||||
|
||||
/**
|
||||
* Specify a batch size, that is, how many entities should be
|
||||
* fetched in each request to the database.
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate;
|
|||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import jakarta.persistence.FindOption;
|
||||
import org.hibernate.graph.RootGraph;
|
||||
import org.hibernate.jdbc.Work;
|
||||
import org.hibernate.query.Query;
|
||||
|
@ -706,12 +707,13 @@ public interface Session extends SharedSessionContract, EntityManager {
|
|||
*
|
||||
* @param entityType the entity type
|
||||
* @param ids the identifiers
|
||||
* @param options options, if any
|
||||
* @return an ordered list of persistent instances, with null elements representing missing
|
||||
* entities
|
||||
* entities
|
||||
* @see #byMultipleIds(Class)
|
||||
* @since 7.0
|
||||
*/
|
||||
<E> List<E> findAll(Class<E> entityType, List<Object> ids);
|
||||
<E> List<E> findAll(Class<E> entityType, List<Object> ids, FindOption... options);
|
||||
|
||||
/**
|
||||
* Return the persistent instance of the given entity class with the given identifier,
|
||||
|
@ -922,7 +924,7 @@ public interface Session extends SharedSessionContract, EntityManager {
|
|||
*
|
||||
* @throws HibernateException If the given class does not resolve as a mapped entity
|
||||
*
|
||||
* @see #findAll(Class, List)
|
||||
* @see #findAll(Class, List, FindOption...)
|
||||
*/
|
||||
<T> MultiIdentifierLoadAccess<T> byMultipleIds(Class<T> entityClass);
|
||||
|
||||
|
|
|
@ -262,7 +262,7 @@ public interface StatelessSession extends SharedSessionContract {
|
|||
* @param entityClass The class of the entity to retrieve
|
||||
* @param ids The ids of the entities to retrieve
|
||||
* @return an ordered list of detached entity instances, with
|
||||
* null elements representing missing entities
|
||||
* null elements representing missing entities
|
||||
* @since 7.0
|
||||
*/
|
||||
<T> List<T> getAll(Class<T> entityClass, List<Object> ids);
|
||||
|
|
|
@ -954,8 +954,8 @@ public class SessionDelegatorBaseImpl implements SessionImplementor {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <E> List<E> findAll(Class<E> entityType, List<Object> ids) {
|
||||
return delegate.findAll( entityType, ids );
|
||||
public <E> List<E> findAll(Class<E> entityType, List<Object> ids, FindOption... options) {
|
||||
return delegate.findAll( entityType, ids, options );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -264,8 +264,8 @@ public class SessionLazyDelegator implements Session {
|
|||
}
|
||||
|
||||
@Override
|
||||
public <E> List<E> findAll(Class<E> entityType, List<Object> ids) {
|
||||
return this.lazySession.get().findAll( entityType, ids );
|
||||
public <E> List<E> findAll(Class<E> entityType, List<Object> ids, FindOption... options) {
|
||||
return this.lazySession.get().findAll( entityType, ids, options );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -6,13 +6,18 @@
|
|||
*/
|
||||
package org.hibernate.internal;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.CacheMode;
|
||||
import org.hibernate.LockOptions;
|
||||
import org.hibernate.MultiIdentifierLoadAccess;
|
||||
import org.hibernate.UnknownProfileException;
|
||||
import org.hibernate.engine.spi.EffectiveEntityGraph;
|
||||
import org.hibernate.engine.spi.LoadQueryInfluencers;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.graph.GraphSemantic;
|
||||
import org.hibernate.graph.RootGraph;
|
||||
import org.hibernate.graph.spi.RootGraphImplementor;
|
||||
|
@ -20,6 +25,8 @@ import org.hibernate.loader.ast.internal.LoaderHelper;
|
|||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.loader.ast.spi.MultiIdLoadOptions;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
|
@ -29,6 +36,7 @@ class MultiIdentifierLoadAccessImpl<T> implements MultiIdentifierLoadAccess<T>,
|
|||
|
||||
private LockOptions lockOptions;
|
||||
private CacheMode cacheMode;
|
||||
private Boolean readOnly;
|
||||
|
||||
private RootGraphImplementor<T> rootGraph;
|
||||
private GraphSemantic graphSemantic;
|
||||
|
@ -38,6 +46,9 @@ class MultiIdentifierLoadAccessImpl<T> implements MultiIdentifierLoadAccess<T>,
|
|||
private boolean returnOfDeletedEntitiesEnabled;
|
||||
private boolean orderedReturnEnabled = true;
|
||||
|
||||
private Set<String> enabledFetchProfiles;
|
||||
private Set<String> disabledFetchProfiles;
|
||||
|
||||
public MultiIdentifierLoadAccessImpl(SessionImpl session, EntityPersister entityPersister) {
|
||||
this.session = session;
|
||||
this.entityPersister = entityPersister;
|
||||
|
@ -60,6 +71,12 @@ class MultiIdentifierLoadAccessImpl<T> implements MultiIdentifierLoadAccess<T>,
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiIdentifierLoadAccess<T> withReadOnly(boolean readOnly) {
|
||||
this.readOnly = readOnly;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiIdentifierLoadAccess<T> with(RootGraph<T> graph, GraphSemantic semantic) {
|
||||
this.rootGraph = (RootGraphImplementor<T>) graph;
|
||||
|
@ -121,6 +138,13 @@ class MultiIdentifierLoadAccessImpl<T> implements MultiIdentifierLoadAccess<T>,
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean getReadOnly(SessionImplementor session) {
|
||||
return readOnly != null
|
||||
? readOnly
|
||||
: session.getLoadQueryInfluencers().getReadOnly();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings( "unchecked" )
|
||||
public <K> List<T> multiLoad(K... ids) {
|
||||
|
@ -128,7 +152,7 @@ class MultiIdentifierLoadAccessImpl<T> implements MultiIdentifierLoadAccess<T>,
|
|||
}
|
||||
|
||||
public List<T> perform(Supplier<List<T>> executor) {
|
||||
CacheMode sessionCacheMode = session.getCacheMode();
|
||||
final CacheMode sessionCacheMode = session.getCacheMode();
|
||||
boolean cacheModeChanged = false;
|
||||
if ( cacheMode != null ) {
|
||||
// naive check for now...
|
||||
|
@ -140,20 +164,17 @@ class MultiIdentifierLoadAccessImpl<T> implements MultiIdentifierLoadAccess<T>,
|
|||
}
|
||||
|
||||
try {
|
||||
if ( graphSemantic != null ) {
|
||||
if ( rootGraph == null ) {
|
||||
throw new IllegalArgumentException( "Graph semantic specified, but no RootGraph was supplied" );
|
||||
}
|
||||
session.getLoadQueryInfluencers().getEffectiveEntityGraph().applyGraph( rootGraph, graphSemantic );
|
||||
}
|
||||
|
||||
final LoadQueryInfluencers influencers = session.getLoadQueryInfluencers();
|
||||
final HashSet<String> fetchProfiles =
|
||||
influencers.adjustFetchProfiles( disabledFetchProfiles, enabledFetchProfiles );
|
||||
final EffectiveEntityGraph effectiveEntityGraph =
|
||||
influencers.applyEntityGraph( rootGraph, graphSemantic );
|
||||
try {
|
||||
return executor.get();
|
||||
}
|
||||
finally {
|
||||
if ( graphSemantic != null ) {
|
||||
session.getLoadQueryInfluencers().getEffectiveEntityGraph().clear();
|
||||
}
|
||||
effectiveEntityGraph.clear();
|
||||
influencers.setEnabledFetchProfileNames( fetchProfiles );
|
||||
}
|
||||
}
|
||||
finally {
|
||||
|
@ -168,12 +189,41 @@ class MultiIdentifierLoadAccessImpl<T> implements MultiIdentifierLoadAccess<T>,
|
|||
@SuppressWarnings( "unchecked" )
|
||||
public <K> List<T> multiLoad(List<K> ids) {
|
||||
if ( ids.isEmpty() ) {
|
||||
return Collections.emptyList();
|
||||
return emptyList();
|
||||
}
|
||||
return perform( () -> (List<T>) entityPersister.multiLoad(
|
||||
ids.toArray( LoaderHelper.createTypedArray( ids.get( 0 ).getClass(), ids.size() ) ),
|
||||
session,
|
||||
this
|
||||
) );
|
||||
else {
|
||||
return perform( () -> (List<T>) entityPersister.multiLoad(
|
||||
ids.toArray( LoaderHelper.createTypedArray( ids.get( 0 ).getClass(), ids.size() ) ),
|
||||
session,
|
||||
this
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiIdentifierLoadAccess<T> enableFetchProfile(String profileName) {
|
||||
if ( !session.getFactory().containsFetchProfileDefinition( profileName ) ) {
|
||||
throw new UnknownProfileException( profileName );
|
||||
}
|
||||
if ( enabledFetchProfiles == null ) {
|
||||
enabledFetchProfiles = new HashSet<>();
|
||||
}
|
||||
enabledFetchProfiles.add( profileName );
|
||||
if ( disabledFetchProfiles != null ) {
|
||||
disabledFetchProfiles.remove( profileName );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MultiIdentifierLoadAccess<T> disableFetchProfile(String profileName) {
|
||||
if ( disabledFetchProfiles == null ) {
|
||||
disabledFetchProfiles = new HashSet<>();
|
||||
}
|
||||
disabledFetchProfiles.add( profileName );
|
||||
if ( enabledFetchProfiles != null ) {
|
||||
enabledFetchProfiles.remove( profileName );
|
||||
}
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -944,22 +944,64 @@ public class SessionImpl
|
|||
|
||||
@Override @Deprecated
|
||||
public Object load(String entityName, Object id) throws HibernateException {
|
||||
return this.byId( entityName ).getReference( id );
|
||||
return byId( entityName ).getReference( id );
|
||||
}
|
||||
|
||||
private <T> MultiIdentifierLoadAccess<T> multiloadAccessWithOptions(Class<T> entityClass, FindOption[] options) {
|
||||
final MultiIdentifierLoadAccess<T> loadAccess = byMultipleIds( entityClass );
|
||||
CacheStoreMode storeMode = getCacheStoreMode();
|
||||
CacheRetrieveMode retrieveMode = getCacheRetrieveMode();
|
||||
LockOptions lockOptions = copySessionLockOptions();
|
||||
for ( FindOption option : options ) {
|
||||
if ( option instanceof CacheStoreMode cacheStoreMode ) {
|
||||
storeMode = cacheStoreMode;
|
||||
}
|
||||
else if ( option instanceof CacheRetrieveMode cacheRetrieveMode ) {
|
||||
retrieveMode = cacheRetrieveMode;
|
||||
}
|
||||
else if ( option instanceof CacheMode cacheMode ) {
|
||||
storeMode = cacheMode.getJpaStoreMode();
|
||||
retrieveMode = cacheMode.getJpaRetrieveMode();
|
||||
}
|
||||
else if ( option instanceof LockModeType lockModeType ) {
|
||||
lockOptions.setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) );
|
||||
}
|
||||
else if ( option instanceof LockMode lockMode ) {
|
||||
lockOptions.setLockMode( lockMode );
|
||||
}
|
||||
else if ( option instanceof LockOptions lockOpts ) {
|
||||
lockOptions = lockOpts;
|
||||
}
|
||||
else if ( option instanceof PessimisticLockScope pessimisticLockScope ) {
|
||||
lockOptions.setLockScope( pessimisticLockScope );
|
||||
}
|
||||
else if ( option instanceof Timeout timeout ) {
|
||||
lockOptions.setTimeOut( timeout.milliseconds() );
|
||||
}
|
||||
else if ( option instanceof EnabledFetchProfile enabledFetchProfile ) {
|
||||
loadAccess.enableFetchProfile( enabledFetchProfile.profileName() );
|
||||
}
|
||||
else if ( option instanceof ReadOnlyMode ) {
|
||||
loadAccess.withReadOnly( option == ReadOnlyMode.READ_ONLY );
|
||||
}
|
||||
}
|
||||
loadAccess.with( lockOptions ).with( interpretCacheMode( storeMode, retrieveMode ) );
|
||||
return loadAccess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <E> List<E> findAll(Class<E> entityType, List<Object> ids) {
|
||||
return this.byMultipleIds( entityType ).multiLoad( ids );
|
||||
public <E> List<E> findAll(Class<E> entityType, List<Object> ids, FindOption... options) {
|
||||
return multiloadAccessWithOptions( entityType, options ).multiLoad( ids );
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T get(Class<T> entityClass, Object id) throws HibernateException {
|
||||
return this.byId( entityClass ).load( id );
|
||||
return byId( entityClass ).load( id );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get(String entityName, Object id) throws HibernateException {
|
||||
return this.byId( entityName ).load( id );
|
||||
return byId( entityName ).load( id );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2360,6 +2402,10 @@ public class SessionImpl
|
|||
else if ( option instanceof CacheRetrieveMode cacheRetrieveMode ) {
|
||||
retrieveMode = cacheRetrieveMode;
|
||||
}
|
||||
else if ( option instanceof CacheMode cacheMode ) {
|
||||
storeMode = cacheMode.getJpaStoreMode();
|
||||
retrieveMode = cacheMode.getJpaRetrieveMode();
|
||||
}
|
||||
else if ( option instanceof LockModeType lockModeType ) {
|
||||
lockOptions.setLockMode( LockModeTypeHelper.getLockMode( lockModeType ) );
|
||||
}
|
||||
|
|
|
@ -9,17 +9,27 @@ package org.hibernate.loader.ast.internal;
|
|||
import org.hibernate.engine.spi.EntityHolder;
|
||||
import org.hibernate.engine.spi.SharedSessionContractImplementor;
|
||||
import org.hibernate.engine.spi.SubselectFetch;
|
||||
import org.hibernate.query.spi.QueryOptions;
|
||||
import org.hibernate.sql.exec.internal.BaseExecutionContext;
|
||||
|
||||
class ExecutionContextWithSubselectFetchHandler extends BaseExecutionContext {
|
||||
|
||||
private final SubselectFetch.RegistrationHandler subSelectFetchableKeysHandler;
|
||||
private final boolean readOnly;
|
||||
|
||||
public ExecutionContextWithSubselectFetchHandler(
|
||||
SharedSessionContractImplementor session,
|
||||
SubselectFetch.RegistrationHandler subSelectFetchableKeysHandler) {
|
||||
this( session, subSelectFetchableKeysHandler, false );
|
||||
}
|
||||
|
||||
public ExecutionContextWithSubselectFetchHandler(
|
||||
SharedSessionContractImplementor session,
|
||||
SubselectFetch.RegistrationHandler subSelectFetchableKeysHandler,
|
||||
boolean readOnly) {
|
||||
super( session );
|
||||
this.subSelectFetchableKeysHandler = subSelectFetchableKeysHandler;
|
||||
this.readOnly = readOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -29,4 +39,8 @@ class ExecutionContextWithSubselectFetchHandler extends BaseExecutionContext {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryOptions getQueryOptions() {
|
||||
return readOnly ? QueryOptions.READ_ONLY : super.getQueryOptions();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ import org.hibernate.sql.results.spi.ManagedResultConsumer;
|
|||
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
|
||||
import static java.lang.Boolean.TRUE;
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.isEmpty;
|
||||
|
||||
/**
|
||||
|
@ -193,7 +194,9 @@ public class MultiIdEntityLoaderArrayParam<E> extends AbstractMultiIdEntityLoade
|
|||
session.getJdbcServices().getJdbcSelectExecutor().executeQuery(
|
||||
jdbcSelectOperation,
|
||||
jdbcParameterBindings,
|
||||
new ExecutionContextWithSubselectFetchHandler( session, subSelectFetchableKeysHandler ),
|
||||
new ExecutionContextWithSubselectFetchHandler( session,
|
||||
subSelectFetchableKeysHandler,
|
||||
TRUE.equals( loadOptions.getReadOnly(session) ) ),
|
||||
RowTransformerStandardImpl.instance(),
|
||||
null,
|
||||
idsToLoadFromDatabase.size(),
|
||||
|
|
|
@ -40,6 +40,8 @@ import org.hibernate.sql.results.spi.ListResultsConsumer;
|
|||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static java.lang.Boolean.TRUE;
|
||||
|
||||
/**
|
||||
* Standard MultiIdEntityLoader
|
||||
*
|
||||
|
@ -157,7 +159,7 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
|||
|
||||
if ( idsInBatch.size() >= maxBatchSize ) {
|
||||
// we've hit the allotted max-batch-size, perform an "intermediate load"
|
||||
loadEntitiesById( idsInBatch, lockOptions, session );
|
||||
loadEntitiesById( idsInBatch, lockOptions, loadOptions, session );
|
||||
idsInBatch.clear();
|
||||
}
|
||||
|
||||
|
@ -169,7 +171,7 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
|||
if ( !idsInBatch.isEmpty() ) {
|
||||
// we still have ids to load from the processing above since the last max-batch-size trigger,
|
||||
// perform a load for them
|
||||
loadEntitiesById( idsInBatch, lockOptions, session );
|
||||
loadEntitiesById( idsInBatch, lockOptions, loadOptions, session );
|
||||
}
|
||||
|
||||
// for each result where we set the EntityKey earlier, replace them
|
||||
|
@ -197,7 +199,8 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
|||
private List<T> loadEntitiesById(
|
||||
List<Object> idsInBatch,
|
||||
LockOptions lockOptions,
|
||||
SharedSessionContractImplementor session) {
|
||||
MultiIdLoadOptions loadOptions,
|
||||
EventSource session) {
|
||||
assert idsInBatch != null;
|
||||
assert ! idsInBatch.isEmpty();
|
||||
|
||||
|
@ -265,7 +268,9 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
|||
return session.getJdbcServices().getJdbcSelectExecutor().list(
|
||||
jdbcSelect,
|
||||
jdbcParameterBindings,
|
||||
new ExecutionContextWithSubselectFetchHandler( session, subSelectFetchableKeysHandler ),
|
||||
new ExecutionContextWithSubselectFetchHandler( session,
|
||||
subSelectFetchableKeysHandler,
|
||||
TRUE.equals( loadOptions.getReadOnly(session) ) ),
|
||||
RowTransformerStandardImpl.instance(),
|
||||
null,
|
||||
ListResultsConsumer.UniqueSemantic.FILTER,
|
||||
|
@ -403,7 +408,7 @@ public class MultiIdEntityLoaderStandard<T> extends AbstractMultiIdEntityLoader<
|
|||
System.arraycopy( ids, idPosition, idsInBatch, 0, batchSize );
|
||||
|
||||
result.addAll(
|
||||
loadEntitiesById( Arrays.asList( idsInBatch ), lockOptions, session )
|
||||
loadEntitiesById( Arrays.asList( idsInBatch ), lockOptions, loadOptions, session )
|
||||
);
|
||||
|
||||
numberOfIdsLeft = numberOfIdsLeft - batchSize;
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.loader.ast.spi;
|
||||
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
|
||||
/**
|
||||
* Encapsulation of the options for loading multiple entities by id
|
||||
*/
|
||||
|
@ -25,4 +27,9 @@ public interface MultiIdLoadOptions extends MultiLoadOptions {
|
|||
* @return the session factory cache is checked first
|
||||
*/
|
||||
boolean isSecondLevelCacheCheckingEnabled();
|
||||
|
||||
/**
|
||||
* Should the entities be loaded in read-only mode?
|
||||
*/
|
||||
Boolean getReadOnly(SessionImplementor session);
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ public class IdentifierLoadAccessImpl<T> implements IdentifierLoadAccess<T>, Jav
|
|||
final HashSet<String> fetchProfiles =
|
||||
influencers.adjustFetchProfiles( disabledFetchProfiles, enabledFetchProfiles );
|
||||
final EffectiveEntityGraph effectiveEntityGraph =
|
||||
session.getLoadQueryInfluencers().applyEntityGraph( rootGraph, graphSemantic);
|
||||
influencers.applyEntityGraph( rootGraph, graphSemantic);
|
||||
try {
|
||||
return executor.get();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
package org.hibernate.orm.test.loading.multiLoad;
|
||||
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import org.hibernate.EnabledFetchProfile;
|
||||
import org.hibernate.Hibernate;
|
||||
import org.hibernate.annotations.FetchProfile;
|
||||
import org.hibernate.annotations.FetchProfileOverride;
|
||||
import org.hibernate.testing.orm.junit.DomainModel;
|
||||
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = {FindAllFetchProfileTest.Record.class, FindAllFetchProfileTest.Owner.class})
|
||||
public class FindAllFetchProfileTest {
|
||||
@Test void test(SessionFactoryScope scope) {
|
||||
scope.inTransaction(s-> {
|
||||
Owner gavin = new Owner("gavin");
|
||||
s.persist(gavin);
|
||||
s.persist(new Record(123L,gavin,"hello earth"));
|
||||
s.persist(new Record(456L,gavin,"hello mars"));
|
||||
});
|
||||
scope.inTransaction(s-> {
|
||||
List<Record> all = s.findAll(Record.class, List.of(456L, 123L, 2L));
|
||||
assertEquals("hello mars",all.get(0).message);
|
||||
assertEquals("hello earth",all.get(1).message);
|
||||
assertNull(all.get(2));
|
||||
assertFalse(Hibernate.isInitialized(all.get(0).owner));
|
||||
assertFalse(Hibernate.isInitialized(all.get(1).owner));
|
||||
});
|
||||
scope.inTransaction(s-> {
|
||||
List<Record> all = s.findAll(Record.class, List.of(456L, 123L),
|
||||
new EnabledFetchProfile("withOwner"));
|
||||
assertEquals("hello mars",all.get(0).message);
|
||||
assertEquals("hello earth",all.get(1).message);
|
||||
assertTrue(Hibernate.isInitialized(all.get(0).owner));
|
||||
assertTrue(Hibernate.isInitialized(all.get(1).owner));
|
||||
});
|
||||
}
|
||||
@Entity
|
||||
@FetchProfile(name = "withOwner")
|
||||
static class Record {
|
||||
@Id Long id;
|
||||
String message;
|
||||
|
||||
@FetchProfileOverride(profile = "withOwner")
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
Owner owner;
|
||||
|
||||
Record(Long id, Owner owner, String message) {
|
||||
this.id = id;
|
||||
this.owner = owner;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
Record() {
|
||||
}
|
||||
}
|
||||
@Entity
|
||||
static class Owner {
|
||||
@Id String name;
|
||||
|
||||
Owner(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
Owner() {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,8 +9,10 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.hibernate.ReadOnlyMode.READ_ONLY;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = FindAllTest.Record.class)
|
||||
|
@ -26,6 +28,13 @@ public class FindAllTest {
|
|||
assertEquals("hello earth",all.get(1).message);
|
||||
assertNull(all.get(2));
|
||||
});
|
||||
scope.inTransaction(s-> {
|
||||
List<Record> all = s.findAll(Record.class, List.of(456L, 123L), READ_ONLY);
|
||||
assertEquals("hello mars",all.get(0).message);
|
||||
assertEquals("hello earth",all.get(1).message);
|
||||
assertTrue(s.isReadOnly(all.get(0)));
|
||||
assertTrue(s.isReadOnly(all.get(1)));
|
||||
});
|
||||
}
|
||||
@Entity
|
||||
static class Record {
|
||||
|
|
|
@ -9,8 +9,8 @@ import org.junit.jupiter.api.Test;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
@SessionFactory
|
||||
@DomainModel(annotatedClasses = GetAllTest.Record.class)
|
||||
|
|
Loading…
Reference in New Issue