HHH-14238 Option to include collection fields in the default fetch group

There is no good reason to lazily-instantiate a collection
wrapper, since that operation never requires access to the
database.

See discussion here:

   https://github.com/hibernate/hibernate-reactive/issues/374
This commit is contained in:
Gavin King 2020-09-18 16:07:33 +02:00 committed by Sanne Grinovero
parent 6eaa3f4415
commit 94b819e70c
9 changed files with 52 additions and 14 deletions

View File

@ -198,6 +198,7 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
private boolean orderInsertsEnabled;
private boolean postInsertIdentifierDelayed;
private boolean enhancementAsProxyEnabled;
private boolean collectionsInDefaultFetchGroupEnabled;
// JPA callbacks
private boolean callbacksEnabled;
@ -1067,6 +1068,11 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
return enhancementAsProxyEnabled;
}
@Override
public boolean isCollectionsInDefaultFetchGroupEnabled() {
return collectionsInDefaultFetchGroupEnabled;
}
@Override
public boolean isOmitJoinOfSuperclassTablesEnabled() {
return omitJoinOfSuperclassTablesEnabled;
@ -1359,6 +1365,10 @@ public class SessionFactoryOptionsBuilder implements SessionFactoryOptions {
mutableJpaCompliance().setCachingCompliance( enabled );
}
public void enableCollectionInDefaultFetchGroup(boolean enabled) {
this.collectionsInDefaultFetchGroupEnabled = enabled;
}
public void disableRefreshDetachedEntity() {
this.allowRefreshDetachedEntity = false;
}

View File

@ -448,6 +448,11 @@ public class AbstractDelegatingSessionFactoryOptions implements SessionFactoryOp
return delegate.isEnhancementAsProxyEnabled();
}
@Override
public boolean isCollectionsInDefaultFetchGroupEnabled() {
return delegate.isCollectionsInDefaultFetchGroupEnabled();
}
@Override
public boolean isOmitJoinOfSuperclassTablesEnabled() {
return delegate.isOmitJoinOfSuperclassTablesEnabled();

View File

@ -315,5 +315,9 @@ public interface SessionFactoryOptions {
return false;
}
default boolean isCollectionsInDefaultFetchGroupEnabled() {
return false;
}
boolean isOmitJoinOfSuperclassTablesEnabled();
}

View File

@ -15,6 +15,7 @@ import org.hibernate.bytecode.BytecodeLogger;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.SessionFactoryRegistry;
import org.hibernate.mapping.Collection;
import org.hibernate.mapping.OneToOne;
import org.hibernate.mapping.Property;
import org.hibernate.mapping.ToOne;
@ -30,7 +31,8 @@ public class EnhancementHelper {
public static boolean includeInBaseFetchGroup(
Property bootMapping,
boolean isEnhanced,
boolean allowEnhancementAsProxy) {
boolean allowEnhancementAsProxy,
boolean collectionsInDefaultFetchGroupEnabled) {
final Value value = bootMapping.getValue();
if ( ! isEnhanced ) {
@ -63,7 +65,8 @@ public class EnhancementHelper {
return true;
}
return ! bootMapping.isLazy();
return collectionsInDefaultFetchGroupEnabled && ( value instanceof Collection )
|| ! bootMapping.isLazy();
}
public static <T> T performWork(

View File

@ -34,7 +34,8 @@ public class LazyAttributesMetadata implements Serializable {
public static LazyAttributesMetadata from(
PersistentClass mappedEntity,
boolean isEnhanced,
boolean allowEnhancementAsProxy) {
boolean allowEnhancementAsProxy,
boolean collectionsInDefaultFetchGroupEnabled) {
final Map<String, LazyAttributeDescriptor> lazyAttributeDescriptorMap = new LinkedHashMap<>();
final Map<String, Set<String>> fetchGroupToAttributesMap = new HashMap<>();
@ -47,7 +48,8 @@ public class LazyAttributesMetadata implements Serializable {
final boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
property,
isEnhanced,
allowEnhancementAsProxy
allowEnhancementAsProxy,
collectionsInDefaultFetchGroupEnabled
);
if ( lazy ) {
final LazyAttributeDescriptor lazyAttributeDescriptor = LazyAttributeDescriptor.from( property, i, x++ );

View File

@ -37,6 +37,7 @@ import org.hibernate.QueryException;
import org.hibernate.Session;
import org.hibernate.StaleObjectStateException;
import org.hibernate.StaleStateException;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.bytecode.enhance.spi.LazyPropertyInitializer;
import org.hibernate.bytecode.enhance.spi.interceptor.BytecodeLazyAttributeInterceptor;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementAsProxyLazinessInterceptor;
@ -586,7 +587,9 @@ public abstract class AbstractEntityPersister
this.navigableRole = new NavigableRole( persistentClass.getEntityName() );
if ( creationContext.getSessionFactory().getSessionFactoryOptions().isSecondLevelCacheEnabled() ) {
SessionFactoryOptions sessionFactoryOptions = creationContext.getSessionFactory().getSessionFactoryOptions();
if ( sessionFactoryOptions.isSecondLevelCacheEnabled() ) {
this.canWriteToCache = determineCanWriteToCache( persistentClass, cacheAccessStrategy );
this.canReadFromCache = determineCanReadFromCache( persistentClass, cacheAccessStrategy );
this.cacheAccessStrategy = cacheAccessStrategy;
@ -737,7 +740,8 @@ public abstract class AbstractEntityPersister
final boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
prop,
entityMetamodel.isInstrumented(),
creationContext.getSessionFactory().getSessionFactoryOptions().isEnhancementAsProxyEnabled()
sessionFactoryOptions.isEnhancementAsProxyEnabled(),
sessionFactoryOptions.isCollectionsInDefaultFetchGroupEnabled()
);
if ( lazy ) {
@ -813,7 +817,8 @@ public abstract class AbstractEntityPersister
final boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
prop,
entityMetamodel.isInstrumented(),
creationContext.getSessionFactory().getSessionFactoryOptions().isEnhancementAsProxyEnabled()
sessionFactoryOptions.isEnhancementAsProxyEnabled(),
sessionFactoryOptions.isCollectionsInDefaultFetchGroupEnabled()
);
while ( colIter.hasNext() ) {
Selectable thing = (Selectable) colIter.next();
@ -924,7 +929,7 @@ public abstract class AbstractEntityPersister
this.cacheEntryHelper = buildCacheEntryHelper();
if ( creationContext.getSessionFactory().getSessionFactoryOptions().isSecondLevelCacheEnabled() ) {
if ( sessionFactoryOptions.isSecondLevelCacheEnabled() ) {
this.invalidateCache = canWriteToCache && determineWhetherToInvalidateCache( persistentClass, creationContext );
}
else {

View File

@ -10,6 +10,7 @@ import java.lang.reflect.Constructor;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
import org.hibernate.engine.internal.UnsavedValueFactory;
import org.hibernate.engine.spi.IdentifierValue;
@ -169,10 +170,12 @@ public final class PropertyFactory {
boolean alwaysDirtyCheck = type.isAssociationType() &&
( (AssociationType) type ).isAlwaysDirtyChecked();
SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions();
final boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
property,
lazyAvailable,
sessionFactory.getSessionFactoryOptions().isEnhancementAsProxyEnabled()
sessionFactoryOptions.isEnhancementAsProxyEnabled(),
sessionFactoryOptions.isCollectionsInDefaultFetchGroupEnabled()
);
switch ( nature ) {

View File

@ -38,11 +38,12 @@ public final class BytecodeEnhancementMetadataPojoImpl implements BytecodeEnhanc
PersistentClass persistentClass,
Set<String> identifierAttributeNames,
CompositeType nonAggregatedCidMapper,
boolean allowEnhancementAsProxy) {
boolean allowEnhancementAsProxy,
boolean collectionsInDefaultFetchGroupEnabled) {
final Class mappedClass = persistentClass.getMappedClass();
final boolean enhancedForLazyLoading = PersistentAttributeInterceptable.class.isAssignableFrom( mappedClass );
final LazyAttributesMetadata lazyAttributesMetadata = enhancedForLazyLoading
? LazyAttributesMetadata.from( persistentClass, true, allowEnhancementAsProxy )
? LazyAttributesMetadata.from( persistentClass, true, allowEnhancementAsProxy, collectionsInDefaultFetchGroupEnabled )
: LazyAttributesMetadata.nonEnhanced( persistentClass.getEntityName() );
return new BytecodeEnhancementMetadataPojoImpl(

View File

@ -19,6 +19,7 @@ import java.util.Set;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.bytecode.enhance.spi.interceptor.EnhancementHelper;
import org.hibernate.bytecode.spi.BytecodeEnhancementMetadata;
import org.hibernate.cfg.NotYetImplementedException;
@ -140,6 +141,8 @@ public class EntityMetamodel implements Serializable {
versioned = persistentClass.isVersioned();
SessionFactoryOptions sessionFactoryOptions = sessionFactory.getSessionFactoryOptions();
if ( persistentClass.hasPojoRepresentation() ) {
final Component identifierMapperComponent = persistentClass.getIdentifierMapper();
final CompositeType nonAggregatedCidMapper;
@ -163,7 +166,8 @@ public class EntityMetamodel implements Serializable {
persistentClass,
idAttributeNames,
nonAggregatedCidMapper,
sessionFactory.getSessionFactoryOptions().isEnhancementAsProxyEnabled()
sessionFactoryOptions.isEnhancementAsProxyEnabled(),
sessionFactoryOptions.isCollectionsInDefaultFetchGroupEnabled()
);
}
else {
@ -245,7 +249,8 @@ public class EntityMetamodel implements Serializable {
boolean lazy = ! EnhancementHelper.includeInBaseFetchGroup(
prop,
bytecodeEnhancementMetadata.isEnhancedForLazyLoading(),
sessionFactory.getSessionFactoryOptions().isEnhancementAsProxyEnabled()
sessionFactoryOptions.isEnhancementAsProxyEnabled(),
sessionFactoryOptions.isCollectionsInDefaultFetchGroupEnabled()
);
if ( lazy ) {
@ -407,7 +412,7 @@ public class EntityMetamodel implements Serializable {
}
entityMode = persistentClass.hasPojoRepresentation() ? EntityMode.POJO : EntityMode.MAP;
final EntityTuplizerFactory entityTuplizerFactory = sessionFactory.getSessionFactoryOptions().getEntityTuplizerFactory();
final EntityTuplizerFactory entityTuplizerFactory = sessionFactoryOptions.getEntityTuplizerFactory();
final String tuplizerClassName = persistentClass.getTuplizerImplClassName( entityMode );
if ( tuplizerClassName == null ) {
entityTuplizer = entityTuplizerFactory.constructDefaultTuplizer( entityMode, this, persistentClass );