implement Session.fetch() for bytecode-enhanced proxies

had to add a way to easily set collectionsInDefaultFetchGroup
This commit is contained in:
Gavin King 2021-12-27 19:08:12 +01:00
parent 8770db00af
commit 313de3f917
6 changed files with 47 additions and 8 deletions

View File

@ -694,6 +694,15 @@ public interface SessionFactoryBuilder {
*/
SessionFactoryBuilder applySqlFunction(String registrationName, SqmFunctionDescriptor functionDescriptor);
/**
* Should collections be included in the default fetch group when bytecode enhancement is used?
*
* @param enabled {@code true} collections should be included
*
* @return {@code this}, for method chaining
*/
SessionFactoryBuilder applyCollectionsInDefaultFetchGroup(boolean enabled);
SessionFactoryBuilder allowOutOfTransactionUpdateOperations(boolean allow);
/**

View File

@ -387,6 +387,12 @@ public class SessionFactoryBuilderImpl implements SessionFactoryBuilderImplement
return this;
}
@Override
public SessionFactoryBuilder applyCollectionsInDefaultFetchGroup(boolean enabled) {
this.optionsBuilder.enableCollectionInDefaultFetchGroup( enabled );
return this;
}
@Override
public SessionFactoryBuilder allowOutOfTransactionUpdateOperations(boolean allow) {
this.optionsBuilder.allowOutOfTransactionUpdateOperations( allow );

View File

@ -110,7 +110,6 @@ import static org.hibernate.cfg.AvailableSettings.JPA_CALLBACKS_ENABLED;
import static org.hibernate.cfg.AvailableSettings.JTA_TRACK_BY_THREAD;
import static org.hibernate.cfg.AvailableSettings.LOG_SESSION_METRICS;
import static org.hibernate.cfg.AvailableSettings.MAX_FETCH_DEPTH;
import static org.hibernate.cfg.AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER;
import static org.hibernate.cfg.AvailableSettings.MULTI_TENANT_IDENTIFIER_RESOLVER;
import static org.hibernate.cfg.AvailableSettings.NATIVE_EXCEPTION_HANDLING_51_COMPLIANCE;
import static org.hibernate.cfg.AvailableSettings.OMIT_JOIN_OF_SUPERCLASS_TABLES;
@ -146,9 +145,9 @@ import static org.hibernate.internal.log.DeprecationLogger.DEPRECATION_LOGGER;
* In-flight state of {@link SessionFactoryOptions}
* during {@link org.hibernate.boot.SessionFactoryBuilder} processing.
*
* The intention is that SessionFactoryBuilder internally creates and populates
* this builder, which is then used to construct the SessionFactoryOptions
* as part of building the SessionFactory ({@link org.hibernate.boot.SessionFactoryBuilder#build})
* The intention is that {@code SessionFactoryBuilder} internally creates and populates
* this builder, which is then used to construct the {@code SessionFactoryOptions}
* as part of building the {@code SessionFactory} ({@link org.hibernate.boot.SessionFactoryBuilder#build})
*
* @author Steve Ebersole
*/

View File

@ -368,6 +368,12 @@ public abstract class AbstractDelegatingSessionFactoryBuilder<T extends SessionF
return getThis();
}
@Override
public SessionFactoryBuilder applyCollectionsInDefaultFetchGroup(boolean enabled) {
delegate.applyCollectionsInDefaultFetchGroup( enabled );
return getThis();
}
@Override
public T allowOutOfTransactionUpdateOperations(boolean allow) {
delegate.allowOutOfTransactionUpdateOperations( allow );

View File

@ -15,6 +15,7 @@ import org.hibernate.LockMode;
import org.hibernate.SessionException;
import org.hibernate.StatelessSession;
import org.hibernate.UnresolvableObjectException;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cache.spi.access.EntityDataAccess;
import org.hibernate.collection.spi.PersistentCollection;
@ -23,6 +24,8 @@ import org.hibernate.engine.internal.Versioning;
import org.hibernate.engine.spi.EntityKey;
import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.PersistentAttributeInterceptable;
import org.hibernate.engine.spi.PersistentAttributeInterceptor;
import org.hibernate.engine.transaction.internal.jta.JtaStatusHelper;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.id.IdentifierGeneratorHelper;
@ -388,6 +391,24 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
}
}
}
else if ( association instanceof PersistentAttributeInterceptable) {
final PersistentAttributeInterceptor interceptor =
( (PersistentAttributeInterceptable) association ).$$_hibernate_getInterceptor();
if ( interceptor instanceof EnhancementAsProxyLazinessInterceptor) {
EnhancementAsProxyLazinessInterceptor proxyInterceptor =
(EnhancementAsProxyLazinessInterceptor) interceptor;
proxyInterceptor.setSession( this );
try {
proxyInterceptor.forceInitialize( association, null );
}
finally {
proxyInterceptor.unsetSession();
if ( persistenceContext.isLoadFinished() ) {
persistenceContext.clear();
}
}
}
}
else if ( association instanceof PersistentCollection ) {
PersistentCollection<?> persistentCollection = (PersistentCollection<?>) association;
if ( !persistentCollection.wasInitialized() ) {

View File

@ -216,7 +216,6 @@ import org.hibernate.sql.SimpleSelect;
import org.hibernate.sql.Template;
import org.hibernate.sql.Update;
import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.spi.FromClauseAccess;
import org.hibernate.sql.ast.spi.SimpleFromClauseAccessImpl;
import org.hibernate.sql.ast.spi.SqlAliasBase;
@ -4252,10 +4251,9 @@ public abstract class AbstractEntityPersister
final EntityKey entityKey = proxyInterceptor.getEntityKey();
final Object identifier = entityKey.getIdentifier();
LoadEvent loadEvent = new LoadEvent( identifier, entity, (EventSource)session, false );
Object loaded = null;
if ( canReadFromCache ) {
if ( canReadFromCache && session instanceof EventSource ) {
LoadEvent loadEvent = new LoadEvent( identifier, entity, (EventSource) session, false );
loaded = CacheEntityLoaderHelper.INSTANCE.loadFromSecondLevelCache( loadEvent, this, entityKey );
}
if ( loaded == null ) {