HHH-16651 cleaner separation of "fetch method" vs "fetch timing"
This commit is contained in:
parent
7ed0241dc5
commit
c636c83d7e
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
new FetchProfile.Fetch(
|
||||||
fetch.entity().getName(),
|
fetch.entity().getName(),
|
||||||
fetch.association(),
|
fetch.association(),
|
||||||
fetch.mode().toString().toLowerCase(Locale.ROOT)
|
fetch.mode(),
|
||||||
|
fetch.fetch()
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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" );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() + "}]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 ) {
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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,18 +7644,19 @@ 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 =
|
||||||
|
( (PluralAttributeMapping) fetchable ).getMappedType()
|
||||||
.getCollectionSemantics()
|
.getCollectionSemantics()
|
||||||
.getCollectionClassification();
|
.getCollectionClassification();
|
||||||
if ( collectionClassification == CollectionClassification.BAG ) {
|
if ( collectionClassification == CollectionClassification.BAG ) {
|
||||||
|
|
Loading…
Reference in New Issue