HHH-16651 support all fetch styles in fetch profiles
Finally, after all these years!
This commit is contained in:
parent
4795b94f68
commit
a5ae1a479a
|
@ -22,7 +22,6 @@ 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;
|
||||||
|
@ -853,9 +852,7 @@ 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() ) {
|
||||||
if ( fetch.mode() != FetchMode.JOIN ) {
|
// TODO: validate which modes are valid where
|
||||||
throw new MappingException( "Only 'FetchMode.JOIN' is currently supported" );
|
|
||||||
}
|
|
||||||
context.getMetadataCollector()
|
context.getMetadataCollector()
|
||||||
.addSecondPass( new FetchOverrideSecondPass( name, fetch, context ) );
|
.addSecondPass( new FetchOverrideSecondPass( name, fetch, context ) );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1486,6 +1486,10 @@ public abstract class CollectionBinder {
|
||||||
setHibernateFetchMode( fetch.value() );
|
setHibernateFetchMode( fetch.value() );
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
buildingContext.getMetadataCollector()
|
||||||
|
.addSecondPass( new FetchSecondPass( fetch, propertyHolder, propertyName, buildingContext ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -361,6 +361,11 @@ public class ToOneBinder {
|
||||||
setHibernateFetchMode( toOne, property, fetch.value() );
|
setHibernateFetchMode( toOne, property, fetch.value() );
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
final MetadataBuildingContext context = toOne.getBuildingContext();
|
||||||
|
context.getMetadataCollector()
|
||||||
|
.addSecondPass( new FetchSecondPass( fetch, propertyHolder, inferredData.getPropertyName(), context ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.engine.profile;
|
package org.hibernate.engine.profile;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Models an individual fetch override within a profile.
|
* Models an individual fetch override within a profile.
|
||||||
*
|
*
|
||||||
|
@ -35,31 +37,25 @@ public class Fetch {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type or style of fetch. For the moment we limit this to
|
* The type or style of fetch.
|
||||||
* join and select, though technically subselect would be valid
|
|
||||||
* here as well; however, to support subselect here would
|
|
||||||
* require major changes to the subselect loading code (which is
|
|
||||||
* needed for other things as well anyway).
|
|
||||||
*/
|
*/
|
||||||
public enum Style {
|
public enum Style {
|
||||||
/**
|
/**
|
||||||
* Fetch via a join
|
* Fetch via a join
|
||||||
*/
|
*/
|
||||||
JOIN( "join" ),
|
JOIN,
|
||||||
/**
|
/**
|
||||||
* Fetch via a subsequent select
|
* Fetch via a subsequent select
|
||||||
*/
|
*/
|
||||||
SELECT( "select" );
|
SELECT,
|
||||||
|
/**
|
||||||
private final String name;
|
* Fetch via a subsequent subselect
|
||||||
|
*/
|
||||||
Style(String name) {
|
SUBSELECT;
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name().toLowerCase(Locale.ROOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,15 +66,14 @@ public class Fetch {
|
||||||
* @return The style; {@link #JOIN} is returned if not recognized
|
* @return The style; {@link #JOIN} is returned if not recognized
|
||||||
*/
|
*/
|
||||||
public static Style parse(String name) {
|
public static Style parse(String name) {
|
||||||
if ( SELECT.name.equals( name ) ) {
|
for ( Style style: values() ) {
|
||||||
return SELECT;
|
if ( style.name().equalsIgnoreCase( name ) ) {
|
||||||
|
return style;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// the default...
|
|
||||||
return JOIN;
|
return JOIN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
|
|
@ -167,4 +167,9 @@ public class FetchProfile {
|
||||||
public boolean isContainsJoinFetchedBag() {
|
public boolean isContainsJoinFetchedBag() {
|
||||||
return containsJoinFetchedBag;
|
return containsJoinFetchedBag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "FetchProfile[" + name + "]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,17 @@ import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.hibernate.Filter;
|
import org.hibernate.Filter;
|
||||||
import org.hibernate.UnknownProfileException;
|
import org.hibernate.UnknownProfileException;
|
||||||
|
import org.hibernate.engine.profile.Fetch;
|
||||||
|
import org.hibernate.engine.profile.FetchProfile;
|
||||||
import org.hibernate.internal.FilterImpl;
|
import org.hibernate.internal.FilterImpl;
|
||||||
import org.hibernate.internal.SessionCreationOptions;
|
import org.hibernate.internal.SessionCreationOptions;
|
||||||
import org.hibernate.loader.ast.spi.CascadingFetchProfile;
|
import org.hibernate.loader.ast.spi.CascadingFetchProfile;
|
||||||
import org.hibernate.persister.collection.CollectionPersister;
|
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 org.hibernate.engine.profile.Fetch.Style.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
|
||||||
* entity. Currently, such influencers are defined as:<ul>
|
* entity. Currently, such influencers are defined as:<ul>
|
||||||
|
@ -157,7 +162,7 @@ public class LoadQueryInfluencers implements Serializable {
|
||||||
*/
|
*/
|
||||||
public Set<String> getEnabledFilterNames() {
|
public Set<String> getEnabledFilterNames() {
|
||||||
if ( enabledFilters == null ) {
|
if ( enabledFilters == null ) {
|
||||||
return Collections.emptySet();
|
return emptySet();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return Collections.unmodifiableSet( enabledFilters.keySet() );
|
return Collections.unmodifiableSet( enabledFilters.keySet() );
|
||||||
|
@ -221,7 +226,7 @@ public class LoadQueryInfluencers implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> getEnabledFetchProfileNames() {
|
public Set<String> getEnabledFetchProfileNames() {
|
||||||
return Objects.requireNonNullElse( enabledFetchProfileNames, Collections.emptySet() );
|
return Objects.requireNonNullElse( enabledFetchProfileNames, emptySet() );
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkFetchProfileName(String name) {
|
private void checkFetchProfileName(String name) {
|
||||||
|
@ -302,7 +307,24 @@ public class LoadQueryInfluencers implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean effectiveSubselectFetchEnabled(CollectionPersister persister) {
|
public boolean effectiveSubselectFetchEnabled(CollectionPersister persister) {
|
||||||
return subselectFetchEnabled || persister.isSubselectLoadable();
|
return subselectFetchEnabled
|
||||||
|
|| persister.isSubselectLoadable()
|
||||||
|
|| isSubselectFetchEnabledInProfile( persister );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isSubselectFetchEnabledInProfile(CollectionPersister persister) {
|
||||||
|
if ( hasEnabledFetchProfiles() ) {
|
||||||
|
for ( String profile : getEnabledFetchProfileNames() ) {
|
||||||
|
final FetchProfile fetchProfile = sessionFactory.getFetchProfile( profile );
|
||||||
|
if ( fetchProfile != null ) {
|
||||||
|
final Fetch fetch = fetchProfile.getFetchByRole( persister.getRole() );
|
||||||
|
if ( fetch != null && fetch.getStyle() == SUBSELECT ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkMutability() {
|
private void checkMutability() {
|
||||||
|
@ -315,6 +337,23 @@ public class LoadQueryInfluencers implements Serializable {
|
||||||
|
|
||||||
public boolean hasSubselectLoadableCollections(EntityPersister persister) {
|
public boolean hasSubselectLoadableCollections(EntityPersister persister) {
|
||||||
return persister.hasSubselectLoadableCollections()
|
return persister.hasSubselectLoadableCollections()
|
||||||
|| subselectFetchEnabled && persister.hasCollections();
|
|| subselectFetchEnabled && persister.hasCollections()
|
||||||
|
|| hasSubselectLoadableCollectionsEnabledInProfile( persister );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hasSubselectLoadableCollectionsEnabledInProfile(EntityPersister persister) {
|
||||||
|
if ( hasEnabledFetchProfiles() ) {
|
||||||
|
for ( String profile : getEnabledFetchProfileNames() ) {
|
||||||
|
final FetchProfile fetchProfile = sessionFactory.getFetchProfile( profile );
|
||||||
|
for ( Fetch fetch : fetchProfile.getFetches().values() ) {
|
||||||
|
// TODO: check that it's relevant to this persister??
|
||||||
|
if ( fetch.getStyle() == SUBSELECT ) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.persister.entity.EntityPersister;
|
|
||||||
import org.hibernate.spi.NavigablePath;
|
import org.hibernate.spi.NavigablePath;
|
||||||
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
import org.hibernate.sql.ast.tree.expression.JdbcParameter;
|
||||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||||
|
|
|
@ -88,6 +88,7 @@ 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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -553,7 +554,7 @@ public class LoaderSelectBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private LoaderSqlAstCreationState createSqlAstCreationState(QuerySpec rootQuerySpec) {
|
private LoaderSqlAstCreationState createSqlAstCreationState(QuerySpec rootQuerySpec) {
|
||||||
final LoaderSqlAstCreationState sqlAstCreationState = new LoaderSqlAstCreationState(
|
return new LoaderSqlAstCreationState(
|
||||||
rootQuerySpec,
|
rootQuerySpec,
|
||||||
new SqlAliasBaseManager(),
|
new SqlAliasBaseManager(),
|
||||||
new SimpleFromClauseAccessImpl(),
|
new SimpleFromClauseAccessImpl(),
|
||||||
|
@ -563,7 +564,6 @@ public class LoaderSelectBuilder {
|
||||||
loadQueryInfluencers,
|
loadQueryInfluencers,
|
||||||
creationContext
|
creationContext
|
||||||
);
|
);
|
||||||
return sqlAstCreationState;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void applyRestriction(
|
private void applyRestriction(
|
||||||
|
@ -875,31 +875,25 @@ public class LoaderSelectBuilder {
|
||||||
for ( String enabledFetchProfileName : loadQueryInfluencers.getEnabledFetchProfileNames() ) {
|
for ( String enabledFetchProfileName : loadQueryInfluencers.getEnabledFetchProfileNames() ) {
|
||||||
final FetchProfile enabledFetchProfile = creationContext.getSessionFactory()
|
final FetchProfile enabledFetchProfile = creationContext.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 = FetchTiming.IMMEDIATE;
|
||||||
joined = joined || profileFetch.getStyle() == org.hibernate.engine.profile.Fetch.Style.JOIN;
|
joined = joined || profileFetch.getStyle() == Style.JOIN;
|
||||||
explicitFetch = shouldExplicitFetch( maximumFetchDepth, fetchable, creationState );
|
explicitFetch = shouldExplicitFetch( maximumFetchDepth, fetchable, creationState );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ( loadQueryInfluencers.getEnabledCascadingFetchProfile() != null ) {
|
else if ( loadQueryInfluencers.getEnabledCascadingFetchProfile() != null ) {
|
||||||
final CascadeStyle cascadeStyle = fetchable.asAttributeMapping().getAttributeMetadata()
|
final CascadeStyle cascadeStyle = fetchable.
|
||||||
.getCascadeStyle();
|
asAttributeMapping().getAttributeMetadata().getCascadeStyle();
|
||||||
final CascadingAction<?> cascadingAction = loadQueryInfluencers.getEnabledCascadingFetchProfile()
|
final CascadingAction<?> cascadingAction =
|
||||||
.getCascadingAction();
|
loadQueryInfluencers.getEnabledCascadingFetchProfile().getCascadingAction();
|
||||||
if ( cascadeStyle == null || cascadeStyle.doCascade( cascadingAction ) ) {
|
if ( cascadeStyle == null || cascadeStyle.doCascade( cascadingAction ) ) {
|
||||||
fetchTiming = FetchTiming.IMMEDIATE;
|
fetchTiming = FetchTiming.IMMEDIATE;
|
||||||
// In 5.x the CascadeEntityJoinWalker only join fetched the first collection fetch
|
// In 5.x the CascadeEntityJoinWalker only join fetched the first collection fetch
|
||||||
if ( isFetchablePluralAttributeMapping ) {
|
joined = !isFetchablePluralAttributeMapping || rowCardinality == RowCardinality.SINGLE;
|
||||||
joined = rowCardinality == RowCardinality.SINGLE;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
joined = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import jakarta.persistence.GeneratedValue;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.ManyToOne;
|
import jakarta.persistence.ManyToOne;
|
||||||
import jakarta.persistence.OneToMany;
|
import jakarta.persistence.OneToMany;
|
||||||
import org.hibernate.Hibernate;
|
|
||||||
import org.hibernate.annotations.Fetch;
|
import org.hibernate.annotations.Fetch;
|
||||||
import org.hibernate.annotations.FetchProfile;
|
import org.hibernate.annotations.FetchProfile;
|
||||||
import org.hibernate.testing.orm.junit.DomainModel;
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
@ -13,10 +12,14 @@ import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static jakarta.persistence.FetchType.LAZY;
|
import static jakarta.persistence.FetchType.LAZY;
|
||||||
|
import static org.hibernate.Hibernate.isInitialized;
|
||||||
import static org.hibernate.annotations.FetchMode.JOIN;
|
import static org.hibernate.annotations.FetchMode.JOIN;
|
||||||
|
import static org.hibernate.annotations.FetchMode.SELECT;
|
||||||
|
import static org.hibernate.annotations.FetchMode.SUBSELECT;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
@ -25,10 +28,19 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
@FetchProfile(name = NewFetchTest.NEW_PROFILE)
|
@FetchProfile(name = NewFetchTest.NEW_PROFILE)
|
||||||
@FetchProfile(name = NewFetchTest.OLD_PROFILE,
|
@FetchProfile(name = NewFetchTest.OLD_PROFILE,
|
||||||
fetchOverrides = @FetchProfile.FetchOverride(entity = NewFetchTest.E.class, association = "f"))
|
fetchOverrides = @FetchProfile.FetchOverride(entity = NewFetchTest.E.class, association = "f"))
|
||||||
|
@FetchProfile(name = NewFetchTest.SUBSELECT_PROFILE)
|
||||||
|
@FetchProfile(name = NewFetchTest.SELECT_PROFILE)
|
||||||
|
@FetchProfile(name = NewFetchTest.JOIN_PROFILE)
|
||||||
|
@FetchProfile(name = NewFetchTest.OLD_SUBSELECT_PROFILE,
|
||||||
|
fetchOverrides = @FetchProfile.FetchOverride(entity = NewFetchTest.F.class, association = "es", mode = SUBSELECT))
|
||||||
public class NewFetchTest {
|
public class NewFetchTest {
|
||||||
|
|
||||||
public static final String NEW_PROFILE = "new-profile";
|
static final String NEW_PROFILE = "new-profile";
|
||||||
public static final String OLD_PROFILE = "old-profile";
|
static final String OLD_PROFILE = "old-profile";
|
||||||
|
static final String SUBSELECT_PROFILE = "subselect-profile";
|
||||||
|
static final String SELECT_PROFILE = "select-profile";
|
||||||
|
static final String JOIN_PROFILE = "join-profile";
|
||||||
|
static final String OLD_SUBSELECT_PROFILE = "old-subselect-profile";
|
||||||
|
|
||||||
@Test void test(SessionFactoryScope scope) {
|
@Test void test(SessionFactoryScope scope) {
|
||||||
scope.inTransaction( s-> {
|
scope.inTransaction( s-> {
|
||||||
|
@ -43,22 +55,109 @@ public class NewFetchTest {
|
||||||
});
|
});
|
||||||
|
|
||||||
F f = scope.fromSession( s -> s.find(F.class, 1));
|
F f = scope.fromSession( s -> s.find(F.class, 1));
|
||||||
assertFalse( Hibernate.isInitialized( f.g ) );
|
assertFalse( isInitialized( f.g ) );
|
||||||
assertFalse( Hibernate.isInitialized( f.es ) );
|
assertFalse( isInitialized( f.es ) );
|
||||||
F ff = scope.fromSession( s -> {
|
F ff = scope.fromSession( s -> {
|
||||||
s.enableFetchProfile(NEW_PROFILE);
|
s.enableFetchProfile(NEW_PROFILE);
|
||||||
return s.find(F.class, 1);
|
return s.find(F.class, 1);
|
||||||
} );
|
} );
|
||||||
assertTrue( Hibernate.isInitialized( ff.g ) );
|
assertTrue( isInitialized( ff.g ) );
|
||||||
assertTrue( Hibernate.isInitialized( ff.es ) );
|
assertTrue( isInitialized( ff.es ) );
|
||||||
|
|
||||||
E e = scope.fromSession( s -> s.find(E.class, 1));
|
E e = scope.fromSession( s -> s.find(E.class, 1));
|
||||||
assertFalse( Hibernate.isInitialized( e.f ) );
|
assertFalse( isInitialized( e.f ) );
|
||||||
E ee = scope.fromSession( s -> {
|
E ee = scope.fromSession( s -> {
|
||||||
s.enableFetchProfile(OLD_PROFILE);
|
s.enableFetchProfile(OLD_PROFILE);
|
||||||
return s.find(E.class, 1);
|
return s.find(E.class, 1);
|
||||||
} );
|
} );
|
||||||
assertTrue( Hibernate.isInitialized( ee.f ) );
|
assertTrue( isInitialized( ee.f ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test void testStyles(SessionFactoryScope scope) {
|
||||||
|
long id = scope.fromTransaction( s-> {
|
||||||
|
G g = new G();
|
||||||
|
F f = new F();
|
||||||
|
E e = new E();
|
||||||
|
f.g = g;
|
||||||
|
e.f = f;
|
||||||
|
s.persist(g);
|
||||||
|
s.persist(f);
|
||||||
|
s.persist(e);
|
||||||
|
return f.id;
|
||||||
|
});
|
||||||
|
F f0 = scope.fromSession( s -> s.find(F.class, id));
|
||||||
|
assertFalse(isInitialized(f0.es));
|
||||||
|
F f1 = scope.fromSession( s -> {
|
||||||
|
s.enableFetchProfile(SELECT_PROFILE);
|
||||||
|
return s.find(F.class, id);
|
||||||
|
});
|
||||||
|
assertTrue(isInitialized(f1.es));
|
||||||
|
F f2 = scope.fromSession( s -> {
|
||||||
|
s.enableFetchProfile(JOIN_PROFILE);
|
||||||
|
return s.find(F.class, id);
|
||||||
|
});
|
||||||
|
assertTrue(isInitialized(f2.es));
|
||||||
|
F f3 = scope.fromSession( s -> {
|
||||||
|
s.enableFetchProfile(SUBSELECT_PROFILE);
|
||||||
|
return s.find(F.class, id);
|
||||||
|
});
|
||||||
|
assertTrue(isInitialized(f3.es));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test void subselectTest(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction(s -> {
|
||||||
|
G g = new G();
|
||||||
|
F f1 = new F();
|
||||||
|
F f2 = new F();
|
||||||
|
E e1 = new E();
|
||||||
|
E e2 = new E();
|
||||||
|
E e3 = new E();
|
||||||
|
E e4 = new E();
|
||||||
|
f1.g = g;
|
||||||
|
f2.g = g;
|
||||||
|
e1.f = f1;
|
||||||
|
e2.f = f1;
|
||||||
|
e3.f = f1;
|
||||||
|
e4.f = f2;
|
||||||
|
s.persist(g);
|
||||||
|
s.persist(f1);
|
||||||
|
s.persist(f2);
|
||||||
|
s.persist(e1);
|
||||||
|
s.persist(e2);
|
||||||
|
s.persist(e3);
|
||||||
|
});
|
||||||
|
scope.inSession( s -> {
|
||||||
|
List<F> fs = s.createSelectionQuery("from F", F.class).getResultList();
|
||||||
|
F f0 = fs.get(0);
|
||||||
|
F f1 = fs.get(1);
|
||||||
|
assertFalse( isInitialized( f0.es ) );
|
||||||
|
assertFalse( isInitialized( f1.es ) );
|
||||||
|
f0.es.size();
|
||||||
|
assertTrue( isInitialized( f0.es ) );
|
||||||
|
assertFalse( isInitialized( f1.es ) );
|
||||||
|
});
|
||||||
|
scope.inSession( s -> {
|
||||||
|
s.enableFetchProfile(SUBSELECT_PROFILE);
|
||||||
|
List<F> fs = s.createSelectionQuery("from F", F.class).getResultList();
|
||||||
|
F f0 = fs.get(0);
|
||||||
|
F f1 = fs.get(1);
|
||||||
|
assertFalse( isInitialized( f0.es ) );
|
||||||
|
assertFalse( isInitialized( f1.es ) );
|
||||||
|
f0.es.size();
|
||||||
|
assertTrue( isInitialized( f0.es ) );
|
||||||
|
assertTrue( isInitialized( f1.es ) );
|
||||||
|
});
|
||||||
|
scope.inSession( s -> {
|
||||||
|
s.enableFetchProfile(OLD_SUBSELECT_PROFILE);
|
||||||
|
List<F> fs = s.createSelectionQuery("from F", F.class).getResultList();
|
||||||
|
F f0 = fs.get(0);
|
||||||
|
F f1 = fs.get(1);
|
||||||
|
assertFalse( isInitialized( f0.es ) );
|
||||||
|
assertFalse( isInitialized( f1.es ) );
|
||||||
|
f0.es.size();
|
||||||
|
assertTrue( isInitialized( f0.es ) );
|
||||||
|
assertTrue( isInitialized( f1.es ) );
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity(name = "E")
|
@Entity(name = "E")
|
||||||
|
@ -77,6 +176,9 @@ public class NewFetchTest {
|
||||||
G g;
|
G g;
|
||||||
@OneToMany(mappedBy = "f")
|
@OneToMany(mappedBy = "f")
|
||||||
@Fetch(value = JOIN, profile = NEW_PROFILE)
|
@Fetch(value = JOIN, profile = NEW_PROFILE)
|
||||||
|
@Fetch(value = SUBSELECT, profile = SUBSELECT_PROFILE)
|
||||||
|
@Fetch(value = SELECT, profile = SELECT_PROFILE)
|
||||||
|
@Fetch(value = JOIN, profile = JOIN_PROFILE)
|
||||||
Set<E> es;
|
Set<E> es;
|
||||||
}
|
}
|
||||||
@Entity(name = "G")
|
@Entity(name = "G")
|
||||||
|
|
Loading…
Reference in New Issue