HHH-16651 cleaner separation of "fetch method" vs "fetch timing"

This commit is contained in:
Gavin 2023-05-23 09:12:59 +02:00 committed by Gavin King
parent 7ed0241dc5
commit c636c83d7e
16 changed files with 228 additions and 67 deletions

View File

@ -7,7 +7,7 @@
package org.hibernate.annotations; package org.hibernate.annotations;
/** /**
* Enumerates strategies for fetching an association from the database. * Enumerates methods for fetching an association from the database.
* <p> * <p>
* The JPA-defined {@link jakarta.persistence.FetchType} enumerates the * The JPA-defined {@link jakarta.persistence.FetchType} enumerates the
* possibilities for <em>when</em> an association might be fetched. This * possibilities for <em>when</em> an association might be fetched. This
@ -46,7 +46,7 @@ public enum FetchMode {
* when it is almost certain that the associated data will be * when it is almost certain that the associated data will be
* available in the second-level cache. * available in the second-level cache.
*/ */
SELECT( org.hibernate.FetchMode.SELECT ), SELECT,
/** /**
* Use an outer join to load all instances of the related entity * Use an outer join to load all instances of the related entity
@ -62,7 +62,7 @@ public enum FetchMode {
* since the associated data is retrieved as part of the initial * since the associated data is retrieved as part of the initial
* query. * query.
*/ */
JOIN( org.hibernate.FetchMode.JOIN ), JOIN,
/** /**
* Use a secondary select with a subselect that re-executes an * Use a secondary select with a subselect that re-executes an
@ -84,15 +84,11 @@ public enum FetchMode {
* re-execution of the initial query within a SQL subselect. * re-execution of the initial query within a SQL subselect.
* </ul> * </ul>
*/ */
SUBSELECT( org.hibernate.FetchMode.SELECT ); SUBSELECT;
private final org.hibernate.FetchMode hibernateFetchMode;
FetchMode(org.hibernate.FetchMode hibernateFetchMode) {
this.hibernateFetchMode = hibernateFetchMode;
}
public org.hibernate.FetchMode getHibernateFetchMode() { public org.hibernate.FetchMode getHibernateFetchMode() {
return hibernateFetchMode; return this == JOIN
? org.hibernate.FetchMode.JOIN
: org.hibernate.FetchMode.SELECT;
} }
} }

View File

@ -6,10 +6,13 @@
*/ */
package org.hibernate.annotations; package org.hibernate.annotations;
import jakarta.persistence.FetchType;
import java.lang.annotation.Repeatable; import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import static jakarta.persistence.FetchType.EAGER;
import static java.lang.annotation.ElementType.PACKAGE; import static java.lang.annotation.ElementType.PACKAGE;
import static java.lang.annotation.ElementType.TYPE; import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
@ -91,8 +94,11 @@ public @interface FetchProfile {
FetchOverride[] fetchOverrides() default {}; FetchOverride[] fetchOverrides() default {};
/** /**
* Overrides the fetching strategy pf a particular association * Overrides the fetching strategy of a particular association in
* in the named fetch profile being defined. * the named fetch profile being defined. If {@link #mode} and
* {@link #fetch} are both unspecified, the strategy defaults to
* {@linkplain FetchType#EAGER eager} {@linkplain FetchMode#JOIN join}
* fetching.
*/ */
@Target({ TYPE, PACKAGE }) @Target({ TYPE, PACKAGE })
@Retention(RUNTIME) @Retention(RUNTIME)
@ -110,9 +116,15 @@ public @interface FetchProfile {
String association(); String association();
/** /**
* The {@linkplain FetchMode fetching strategy} to apply to * The {@linkplain FetchMode method} used for fetching the
* the association in the fetch profile being defined. * association in the fetch profile being defined.
*/ */
FetchMode mode() default JOIN; FetchMode mode() default JOIN;
/**
* The {@link FetchType timing} of association fetching in
* the fetch profile being defined.
*/
FetchType fetch() default EAGER;
} }
} }

View File

@ -12,6 +12,7 @@ import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
import jakarta.persistence.FetchType;
import org.hibernate.AnnotationException; import org.hibernate.AnnotationException;
import org.hibernate.MappingException; import org.hibernate.MappingException;
import org.hibernate.annotations.CollectionTypeRegistration; import org.hibernate.annotations.CollectionTypeRegistration;
@ -22,6 +23,7 @@ import org.hibernate.annotations.ConverterRegistration;
import org.hibernate.annotations.ConverterRegistrations; import org.hibernate.annotations.ConverterRegistrations;
import org.hibernate.annotations.EmbeddableInstantiatorRegistration; import org.hibernate.annotations.EmbeddableInstantiatorRegistration;
import org.hibernate.annotations.EmbeddableInstantiatorRegistrations; import org.hibernate.annotations.EmbeddableInstantiatorRegistrations;
import org.hibernate.annotations.FetchMode;
import org.hibernate.annotations.FetchProfile; import org.hibernate.annotations.FetchProfile;
import org.hibernate.annotations.FetchProfile.FetchOverride; import org.hibernate.annotations.FetchProfile.FetchOverride;
import org.hibernate.annotations.FetchProfiles; import org.hibernate.annotations.FetchProfiles;
@ -852,7 +854,11 @@ public final class AnnotationBinder {
final String name = fetchProfile.name(); final String name = fetchProfile.name();
if ( reuseOrCreateFetchProfile( context, name ) ) { if ( reuseOrCreateFetchProfile( context, name ) ) {
for ( FetchOverride fetch : fetchProfile.fetchOverrides() ) { for ( FetchOverride fetch : fetchProfile.fetchOverrides() ) {
// TODO: validate which modes are valid where if ( fetch.fetch() == FetchType.LAZY && fetch.mode() == FetchMode.JOIN ) {
throw new AnnotationException( "Fetch profile '" + name
+ "' has a '@FetchOverride' with 'fetch=LAZY' and 'mode=JOIN'"
+ " (join fetching is eager by nature)");
}
context.getMetadataCollector() context.getMetadataCollector()
.addSecondPass( new FetchOverrideSecondPass( name, fetch, context ) ); .addSecondPass( new FetchOverrideSecondPass( name, fetch, context ) );
} }

View File

@ -13,7 +13,6 @@ import org.hibernate.boot.spi.SecondPass;
import org.hibernate.mapping.FetchProfile; import org.hibernate.mapping.FetchProfile;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import java.util.Locale;
import java.util.Map; import java.util.Map;
/** /**
@ -43,9 +42,12 @@ public class FetchOverrideSecondPass implements SecondPass {
final FetchProfile profile = buildingContext.getMetadataCollector().getFetchProfile( fetchProfileName ); final FetchProfile profile = buildingContext.getMetadataCollector().getFetchProfile( fetchProfileName );
// we already know that the FetchProfile exists and is good to use // we already know that the FetchProfile exists and is good to use
profile.addFetch( profile.addFetch(
fetch.entity().getName(), new FetchProfile.Fetch(
fetch.association(), fetch.entity().getName(),
fetch.mode().toString().toLowerCase(Locale.ROOT) fetch.association(),
fetch.mode(),
fetch.fetch()
)
); );
} }
} }

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.engine; package org.hibernate.engine;
import jakarta.persistence.FetchType;
/** /**
* Enumeration of values describing <em>when</em> fetching should occur. * Enumeration of values describing <em>when</em> fetching should occur.
* *
@ -20,5 +22,16 @@ public enum FetchTiming {
/** /**
* Performing fetching later, when needed. Also called lazy fetching. * Performing fetching later, when needed. Also called lazy fetching.
*/ */
DELAYED DELAYED;
public static FetchTiming forType(FetchType type) {
switch ( type ) {
case EAGER:
return IMMEDIATE;
case LAZY:
return DELAYED;
default:
throw new IllegalArgumentException( "Unknown FetchType" );
}
}
} }

View File

@ -6,8 +6,15 @@
*/ */
package org.hibernate.engine.profile; package org.hibernate.engine.profile;
import org.hibernate.AssertionFailure;
import org.hibernate.annotations.FetchMode;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import java.util.Locale; import java.util.Locale;
import static org.hibernate.engine.FetchTiming.IMMEDIATE;
/** /**
* Models an individual fetch override within a {@link FetchProfile}. * Models an individual fetch override within a {@link FetchProfile}.
* *
@ -15,17 +22,34 @@ import java.util.Locale;
*/ */
public class Fetch { public class Fetch {
private final Association association; private final Association association;
private final Style style; private final FetchStyle method;
private final FetchTiming timing;
/** /**
* Constructs a {@link Fetch}. * Constructs a {@link Fetch}.
* *
* @param association The association to be fetched * @param association The association to be fetched
* @param style How to fetch it * @param style How to fetch it
*
* @deprecated use {@link #Fetch(Association,FetchStyle,FetchTiming)}
*/ */
@Deprecated(forRemoval = true)
public Fetch(Association association, Style style) { public Fetch(Association association, Style style) {
this.association = association; this.association = association;
this.style = style; this.method = style.toFetchStyle();
this.timing = IMMEDIATE;
}
/**
* Constructs a {@link Fetch}.
*
* @param association The association to be fetched
* @param method How to fetch it
*/
public Fetch(Association association, FetchStyle method, FetchTiming timing) {
this.association = association;
this.method = method;
this.timing = timing;
} }
/** /**
@ -37,14 +61,34 @@ public class Fetch {
/** /**
* The fetch style applied to the association. * The fetch style applied to the association.
*
* @deprecated use {@link #getMethod()}
*/ */
@Deprecated(forRemoval = true)
public Style getStyle() { public Style getStyle() {
return style; return Style.fromFetchStyle( method );
}
/**
* The fetch method to be applied to the association.
*/
public FetchStyle getMethod() {
return method;
}
/**
* The fetch timing to be applied to the association.
*/
public FetchTiming getTiming() {
return timing;
} }
/** /**
* The type or style of fetch. * The type or style of fetch.
*
* @deprecated Use {@link FetchStyle}
*/ */
@Deprecated(forRemoval = true)
public enum Style { public enum Style {
/** /**
* Fetch via a join * Fetch via a join
@ -59,6 +103,32 @@ public class Fetch {
*/ */
SUBSELECT; SUBSELECT;
public FetchStyle toFetchStyle() {
switch (this) {
case SELECT:
return FetchStyle.SELECT;
case SUBSELECT:
return FetchStyle.SUBSELECT;
case JOIN:
return FetchStyle.JOIN;
default:
throw new AssertionFailure("Unknown Fetch.Style");
}
}
static Style fromFetchStyle(FetchStyle fetchStyle) {
switch (fetchStyle) {
case SELECT:
return SELECT;
case SUBSELECT:
return SUBSELECT;
case JOIN:
return JOIN;
default:
throw new IllegalArgumentException("Unhandled FetchStyle");
}
}
@Override @Override
public String toString() { public String toString() {
return name().toLowerCase(Locale.ROOT); return name().toLowerCase(Locale.ROOT);
@ -79,10 +149,23 @@ public class Fetch {
} }
return JOIN; return JOIN;
} }
public static Style forMethod(FetchMode fetchMode) {
switch ( fetchMode ) {
case JOIN:
return JOIN;
case SELECT:
return SELECT;
case SUBSELECT:
return SUBSELECT;
default:
throw new IllegalArgumentException( "Unknown FetchMode" );
}
}
} }
@Override @Override
public String toString() { public String toString() {
return "Fetch[" + style + "{" + association.getRole() + "}]"; return "Fetch[" + method + "{" + association.getRole() + "}]";
} }
} }

View File

@ -15,6 +15,8 @@ import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.type.BagType; import org.hibernate.type.BagType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
import static org.hibernate.engine.FetchStyle.JOIN;
/** /**
* The runtime representation of a Hibernate * The runtime representation of a Hibernate
* {@linkplain org.hibernate.annotations.FetchProfile fetch profile} * {@linkplain org.hibernate.annotations.FetchProfile fetch profile}
@ -97,7 +99,7 @@ public class FetchProfile {
// couple of things for which to account in the case of collection // couple of things for which to account in the case of collection
// join fetches // join fetches
if ( Fetch.Style.JOIN == fetch.getStyle() ) { if ( fetch.getMethod() == JOIN ) {
// first, if this is a bag we need to ignore it if we previously // first, if this is a bag we need to ignore it if we previously
// processed collection join fetches // processed collection join fetches
if ( associationType instanceof BagType ) { if ( associationType instanceof BagType ) {

View File

@ -6,8 +6,6 @@
*/ */
package org.hibernate.engine.profile.internal; package org.hibernate.engine.profile.internal;
import org.hibernate.engine.profile.Fetch;
/** /**
* Commonality between entities and collections as something that can be affected by fetch profiles. * Commonality between entities and collections as something that can be affected by fetch profiles.
* *
@ -17,5 +15,5 @@ public interface FetchProfileAffectee {
/** /**
* Register the profile name with the entity/collection * Register the profile name with the entity/collection
*/ */
void registerAffectingFetchProfile(String fetchProfileName, Fetch.Style fetchStyle); void registerAffectingFetchProfile(String fetchProfileName);
} }

View File

@ -26,7 +26,7 @@ import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import static java.util.Collections.emptySet; import static java.util.Collections.emptySet;
import static org.hibernate.engine.profile.Fetch.Style.SUBSELECT; import static org.hibernate.engine.FetchStyle.SUBSELECT;
/** /**
* Centralize all options which can influence the SQL query needed to load an * Centralize all options which can influence the SQL query needed to load an
@ -318,7 +318,7 @@ public class LoadQueryInfluencers implements Serializable {
final FetchProfile fetchProfile = sessionFactory.getFetchProfile( profile ); final FetchProfile fetchProfile = sessionFactory.getFetchProfile( profile );
if ( fetchProfile != null ) { if ( fetchProfile != null ) {
final Fetch fetch = fetchProfile.getFetchByRole( persister.getRole() ); final Fetch fetch = fetchProfile.getFetchByRole( persister.getRole() );
if ( fetch != null && fetch.getStyle() == SUBSELECT ) { if ( fetch != null && fetch.getMethod() == SUBSELECT) {
return true; return true;
} }
} }
@ -347,7 +347,7 @@ public class LoadQueryInfluencers implements Serializable {
final FetchProfile fetchProfile = sessionFactory.getFetchProfile( profile ); final FetchProfile fetchProfile = sessionFactory.getFetchProfile( profile );
for ( Fetch fetch : fetchProfile.getFetches().values() ) { for ( Fetch fetch : fetchProfile.getFetches().values() ) {
// TODO: check that it's relevant to this persister?? // TODO: check that it's relevant to this persister??
if ( fetch.getStyle() == SUBSELECT ) { if ( fetch.getMethod() == SUBSELECT ) {
return true; return true;
} }
} }

View File

@ -8,6 +8,8 @@ package org.hibernate.internal;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.boot.spi.MetadataImplementor;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.profile.Association; import org.hibernate.engine.profile.Association;
import org.hibernate.engine.profile.Fetch; import org.hibernate.engine.profile.Fetch;
import org.hibernate.engine.profile.FetchProfile; import org.hibernate.engine.profile.FetchProfile;
@ -44,24 +46,24 @@ public class FetchProfileHelper {
org.hibernate.mapping.FetchProfile mappingProfile) { org.hibernate.mapping.FetchProfile mappingProfile) {
final String profileName = mappingProfile.getName(); final String profileName = mappingProfile.getName();
final FetchProfile fetchProfile = new FetchProfile( profileName ); final FetchProfile fetchProfile = new FetchProfile( profileName );
for ( org.hibernate.mapping.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) { for ( org.hibernate.mapping.FetchProfile.Fetch mappingFetch : mappingProfile.getFetches() ) {
// resolve the persister owning the fetch // resolve the persister owning the fetch
final EntityPersister owner = getEntityPersister( mappingMetamodel, fetchProfile, mappingFetch ); final EntityPersister owner = getEntityPersister( mappingMetamodel, fetchProfile, mappingFetch );
( (FetchProfileAffectee) owner ).registerAffectingFetchProfile( profileName, null ); ( (FetchProfileAffectee) owner ).registerAffectingFetchProfile( profileName);
final Association association = new Association( owner, mappingFetch.getAssociation() ); final Association association = new Association( owner, mappingFetch.getAssociation() );
final Fetch.Style fetchStyle = Fetch.Style.parse( mappingFetch.getStyle() ); final FetchStyle fetchStyle = Fetch.Style.forMethod( mappingFetch.getMethod() ).toFetchStyle();
final FetchTiming fetchTiming = FetchTiming.forType( mappingFetch.getType() );
// validate the specified association fetch // validate the specified association fetch
final ModelPart fetchablePart = owner.findByPath( association.getAssociationPath() ); final ModelPart fetchablePart = owner.findByPath( association.getAssociationPath() );
validateFetchablePart( fetchablePart, profileName, association ); validateFetchablePart( fetchablePart, profileName, association );
if ( fetchablePart instanceof FetchProfileAffectee ) { if ( fetchablePart instanceof FetchProfileAffectee ) {
( (FetchProfileAffectee) fetchablePart ).registerAffectingFetchProfile( profileName, fetchStyle ); ( (FetchProfileAffectee) fetchablePart ).registerAffectingFetchProfile( profileName );
} }
// then register the association with the FetchProfile // then register the association with the FetchProfile
fetchProfile.addFetch( new Fetch( association, fetchStyle ) ); fetchProfile.addFetch( new Fetch( association, fetchStyle, fetchTiming ) );
} }
return fetchProfile; return fetchProfile;
} }
@ -86,7 +88,7 @@ public class FetchProfileHelper {
private static boolean isAssociation(ModelPart fetchablePart) { private static boolean isAssociation(ModelPart fetchablePart) {
return fetchablePart instanceof EntityValuedModelPart return fetchablePart instanceof EntityValuedModelPart
|| fetchablePart instanceof PluralAttributeMapping; || fetchablePart instanceof PluralAttributeMapping;
} }
private static EntityPersister getEntityPersister( private static EntityPersister getEntityPersister(
@ -95,7 +97,7 @@ public class FetchProfileHelper {
org.hibernate.mapping.FetchProfile.Fetch mappingFetch) { org.hibernate.mapping.FetchProfile.Fetch mappingFetch) {
final String entityName = mappingMetamodel.getImportedName( mappingFetch.getEntity() ); final String entityName = mappingMetamodel.getImportedName( mappingFetch.getEntity() );
if ( entityName != null ) { if ( entityName != null ) {
EntityPersister persister = mappingMetamodel.getEntityDescriptor( entityName ); final EntityPersister persister = mappingMetamodel.getEntityDescriptor( entityName );
if ( persister != null ) { if ( persister != null ) {
return persister; return persister;
} }

View File

@ -88,7 +88,6 @@ import org.hibernate.sql.results.internal.StandardEntityGraphTraversalStateImpl;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.hibernate.engine.profile.Fetch.Style;
import static org.hibernate.query.results.ResultsHelper.attributeName; import static org.hibernate.query.results.ResultsHelper.attributeName;
/** /**
@ -878,8 +877,8 @@ public class LoaderSelectBuilder {
final org.hibernate.engine.profile.Fetch profileFetch = final org.hibernate.engine.profile.Fetch profileFetch =
enabledFetchProfile.getFetchByRole( fetchableRole ); enabledFetchProfile.getFetchByRole( fetchableRole );
if ( profileFetch != null ) { if ( profileFetch != null ) {
fetchTiming = FetchTiming.IMMEDIATE; fetchTiming = profileFetch.getTiming();
joined = joined || profileFetch.getStyle() == Style.JOIN; joined = joined || profileFetch.getMethod() == FetchStyle.JOIN;
explicitFetch = shouldExplicitFetch( maximumFetchDepth, fetchable, creationState ); explicitFetch = shouldExplicitFetch( maximumFetchDepth, fetchable, creationState );
} }
} }

View File

@ -5,7 +5,14 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.mapping; package org.hibernate.mapping;
import jakarta.persistence.FetchType;
import org.hibernate.annotations.FetchMode;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Locale;
import static jakarta.persistence.FetchType.EAGER;
/** /**
* A mapping model object representing a {@link org.hibernate.annotations.FetchProfile}. * A mapping model object representing a {@link org.hibernate.annotations.FetchProfile}.
@ -63,9 +70,19 @@ public class FetchProfile {
* @param entity The entity which contains the association to be fetched * @param entity The entity which contains the association to be fetched
* @param association The association to fetch * @param association The association to fetch
* @param style The style of fetch to apply * @param style The style of fetch to apply
*
* @deprecated use {@link #addFetch(Fetch)}
*/ */
@Deprecated(forRemoval = true)
public void addFetch(String entity, String association, String style) { public void addFetch(String entity, String association, String style) {
fetches.add( new Fetch( entity, association, style ) ); addFetch( new Fetch( entity, association, style ) );
}
/**
* Adds a fetch to this profile.
*/
public void addFetch(Fetch fetch) {
fetches.add( fetch );
} }
@Override @Override
@ -89,17 +106,39 @@ public class FetchProfile {
/** /**
* Defines an individual association fetch within the given profile. * An individual association fetch within the given profile.
*/ */
public static class Fetch { public static class Fetch {
private final String entity; private final String entity;
private final String association; private final String association;
private final String style; private final FetchMode method;
private final FetchType type;
public Fetch(String entity, String association, FetchMode method, FetchType type) {
this.entity = entity;
this.association = association;
this.method = method;
this.type = type;
}
/**
* @deprecated use {@link FetchProfile.Fetch#Fetch(String,String,FetchMode,FetchType)}
*/
@Deprecated(forRemoval = true)
public Fetch(String entity, String association, String style) { public Fetch(String entity, String association, String style) {
this.entity = entity; this.entity = entity;
this.association = association; this.association = association;
this.style = style; this.method = fetchMode( style );
this.type = EAGER;
}
private FetchMode fetchMode(String style) {
for ( FetchMode mode: FetchMode.values() ) {
if ( mode.name().equalsIgnoreCase( style ) ) {
return mode;
}
}
throw new IllegalArgumentException( "Unknown FetchMode: " + style );
} }
public String getEntity() { public String getEntity() {
@ -110,8 +149,20 @@ public class FetchProfile {
return association; return association;
} }
/**
* @deprecated use {@link #getMethod()}
*/
@Deprecated(forRemoval = true)
public String getStyle() { public String getStyle() {
return style; return method.toString().toLowerCase(Locale.ROOT);
}
public FetchMode getMethod() {
return method;
}
public FetchType getType() {
return type;
} }
} }
} }

View File

@ -901,9 +901,9 @@ public class PluralAttributeMappingImpl
} }
@Override @Override
public void registerAffectingFetchProfile(String fetchProfileName, org.hibernate.engine.profile.Fetch.Style fetchStyle) { public void registerAffectingFetchProfile(String fetchProfileName) {
if ( collectionDescriptor instanceof FetchProfileAffectee ) { if ( collectionDescriptor instanceof FetchProfileAffectee ) {
( (FetchProfileAffectee) collectionDescriptor ).registerAffectingFetchProfile( fetchProfileName, fetchStyle ); ( (FetchProfileAffectee) collectionDescriptor ).registerAffectingFetchProfile( fetchProfileName);
} }
} }

View File

@ -30,7 +30,6 @@ import org.hibernate.engine.jdbc.mutation.ParameterUsage;
import org.hibernate.engine.jdbc.mutation.internal.MutationQueryOptions; import org.hibernate.engine.jdbc.mutation.internal.MutationQueryOptions;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator; import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.profile.Fetch;
import org.hibernate.engine.profile.internal.FetchProfileAffectee; import org.hibernate.engine.profile.internal.FetchProfileAffectee;
import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle; import org.hibernate.engine.spi.ExecuteUpdateResultCheckStyle;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
@ -127,6 +126,7 @@ import java.sql.SQLException;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -232,7 +232,7 @@ public abstract class AbstractCollectionPersister
private CollectionElementLoaderByIndex collectionElementLoaderByIndex; private CollectionElementLoaderByIndex collectionElementLoaderByIndex;
private PluralAttributeMapping attributeMapping; private PluralAttributeMapping attributeMapping;
private volatile Map<String, Fetch.Style> affectingFetchProfiles; private volatile Set<String> affectingFetchProfiles;
@Deprecated(since = "6.0") @Deprecated(since = "6.0")
@ -1556,17 +1556,17 @@ public abstract class AbstractCollectionPersister
} }
@Override @Override
public void registerAffectingFetchProfile(String fetchProfileName, Fetch.Style fetchStyle) { public void registerAffectingFetchProfile(String fetchProfileName) {
if ( affectingFetchProfiles == null ) { if ( affectingFetchProfiles == null ) {
affectingFetchProfiles = new HashMap<>(); affectingFetchProfiles = new HashSet<>();
} }
affectingFetchProfiles.put( fetchProfileName, fetchStyle ); affectingFetchProfiles.add( fetchProfileName );
} }
@Override @Override
public boolean isAffectedByEnabledFetchProfiles(LoadQueryInfluencers influencers) { public boolean isAffectedByEnabledFetchProfiles(LoadQueryInfluencers influencers) {
if ( affectingFetchProfiles != null && influencers.hasEnabledFetchProfiles() ) { if ( affectingFetchProfiles != null && influencers.hasEnabledFetchProfiles() ) {
for ( String profileName : affectingFetchProfiles.keySet() ) { for ( String profileName : affectingFetchProfiles ) {
if ( influencers.isFetchProfileEnabled( profileName ) ) { if ( influencers.isFetchProfileEnabled( profileName ) ) {
return true; return true;
} }

View File

@ -3518,11 +3518,6 @@ public abstract class AbstractEntityPersister
affectingFetchProfileNames.add( fetchProfileName ); affectingFetchProfileNames.add( fetchProfileName );
} }
@Override
public void registerAffectingFetchProfile(String fetchProfileName, org.hibernate.engine.profile.Fetch.Style fetchStyle) {
registerAffectingFetchProfile( fetchProfileName );
}
@Override @Override
public boolean isAffectedByEntityGraph(LoadQueryInfluencers loadQueryInfluencers) { public boolean isAffectedByEntityGraph(LoadQueryInfluencers loadQueryInfluencers) {
final RootGraphImplementor<?> graph = loadQueryInfluencers.getEffectiveEntityGraph().getGraph(); final RootGraphImplementor<?> graph = loadQueryInfluencers.getEffectiveEntityGraph().getGraph();

View File

@ -38,6 +38,7 @@ import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.function.TimestampaddFunction; import org.hibernate.dialect.function.TimestampaddFunction;
import org.hibernate.dialect.function.TimestampdiffFunction; import org.hibernate.dialect.function.TimestampdiffFunction;
import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.profile.FetchProfile; import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
@ -7643,20 +7644,21 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final FetchProfile enabledFetchProfile = getCreationContext() final FetchProfile enabledFetchProfile = getCreationContext()
.getSessionFactory() .getSessionFactory()
.getFetchProfile( enabledFetchProfileName ); .getFetchProfile( enabledFetchProfileName );
final org.hibernate.engine.profile.Fetch profileFetch = enabledFetchProfile.getFetchByRole( final org.hibernate.engine.profile.Fetch profileFetch =
fetchableRole ); enabledFetchProfile.getFetchByRole( fetchableRole );
if ( profileFetch != null ) { if ( profileFetch != null ) {
fetchTiming = FetchTiming.IMMEDIATE; fetchTiming = profileFetch.getTiming();
joined = joined || profileFetch.getStyle() == org.hibernate.engine.profile.Fetch.Style.JOIN; joined = joined || profileFetch.getMethod() == FetchStyle.JOIN;
if ( shouldExplicitFetch( maxDepth, fetchable ) ) { if ( shouldExplicitFetch( maxDepth, fetchable ) ) {
explicitFetch = true; explicitFetch = true;
} }
if ( currentBagRole != null && fetchable instanceof PluralAttributeMapping ) { if ( currentBagRole != null && fetchable instanceof PluralAttributeMapping ) {
final CollectionClassification collectionClassification = ( (PluralAttributeMapping) fetchable ).getMappedType() final CollectionClassification collectionClassification =
.getCollectionSemantics() ( (PluralAttributeMapping) fetchable ).getMappedType()
.getCollectionClassification(); .getCollectionSemantics()
.getCollectionClassification();
if ( collectionClassification == CollectionClassification.BAG ) { if ( collectionClassification == CollectionClassification.BAG ) {
// To avoid a MultipleBagFetchException due to fetch profiles in a circular model, // To avoid a MultipleBagFetchException due to fetch profiles in a circular model,
// we skip join fetching in case we encounter an existing bag role // we skip join fetching in case we encounter an existing bag role