1212import jakarta .persistence .ManyToMany ;
1313import jakarta .persistence .ManyToOne ;
1414import jakarta .persistence .OneToMany ;
15-
1615import org .hibernate .Hibernate ;
17- import org .hibernate .annotations .Fetch ;
1816import org .hibernate .annotations .FetchMode ;
17+ import org .hibernate .annotations .FetchProfile ;
18+ import org .hibernate .annotations .FetchProfileOverride ;
1919import org .hibernate .engine .spi .BatchFetchQueue ;
2020import org .hibernate .engine .spi .EntityKey ;
2121import org .hibernate .engine .spi .SessionImplementor ;
2222import org .hibernate .persister .entity .EntityPersister ;
23-
24- import org .hibernate .testing .orm .junit .EntityManagerFactoryScope ;
25- import org .hibernate .testing .orm .junit .Jpa ;
26- import org .junit .jupiter .api .BeforeAll ;
23+ import org . hibernate . testing . orm . junit . DomainModel ;
24+ import org .hibernate .testing .orm .junit .SessionFactory ;
25+ import org .hibernate .testing .orm .junit .SessionFactoryScope ;
26+ import org .junit .jupiter .api .BeforeEach ;
2727import org .junit .jupiter .api .Test ;
2828
2929import java .util .HashSet ;
3333import static org .hamcrest .Matchers .is ;
3434import static org .hamcrest .Matchers .notNullValue ;
3535
36- @ Jpa (annotatedClasses = {
36+ @ SessionFactory
37+ @ DomainModel (annotatedClasses = {
3738 GenerateSubselectsOnJoinedAssociationTest .LazySelectRoot .class ,
3839 GenerateSubselectsOnJoinedAssociationTest .LazySelectNode .class
3940})
4041public class GenerateSubselectsOnJoinedAssociationTest {
4142
42- @ BeforeAll
43- static void setup (final EntityManagerFactoryScope scope ) {
43+ private EntityKey key1 ;
44+ private EntityKey key2 ;
45+ private EntityKey key3 ;
46+
47+ @ BeforeEach
48+ void setup (final SessionFactoryScope scope ) {
49+ final EntityPersister persister = scope .getSessionFactory ().getMappingMetamodel ()
50+ .getEntityDescriptor ( LazySelectNode .class );
51+
52+ key1 = new EntityKey ( 10 , persister );
53+ key2 = new EntityKey ( 20 , persister );
54+ key3 = new EntityKey ( 30 , persister );
55+
4456 scope .inTransaction ( em -> {
57+ if ( em .find ( LazySelectRoot .class , 1 ) != null ) {
58+ return ;
59+ }
60+
4561 final LazySelectNode rootNode = new LazySelectNode ();
4662 rootNode .id = 10 ;
4763
@@ -68,64 +84,114 @@ static void setup(final EntityManagerFactoryScope scope) {
6884 }
6985
7086 @ Test
71- void testSubselectFetchingFromFind (final EntityManagerFactoryScope scope ) {
72- final LazySelectRoot root = scope .fromTransaction ( em -> {
73- final SessionImplementor session = em . unwrap ( SessionImplementor . class );
74- final EntityPersister persister = session . getEntityPersister ( null , new LazySelectNode () );
75- final EntityKey key1 = session .generateEntityKey ( 10 , persister );
76- final EntityKey key2 = session . generateEntityKey ( 20 , persister );
77- final EntityKey key3 = session . generateEntityKey ( 30 , persister );
78-
79- final LazySelectRoot in = em . find ( LazySelectRoot . class , 1L );
80-
81- final BatchFetchQueue batchFetchQueue = session . getPersistenceContextInternal (). getBatchFetchQueue ( );
82- assertThat ( batchFetchQueue . getSubselect ( key1 ), is ( notNullValue () ) );
83- assertThat ( batchFetchQueue . getSubselect ( key2 ), is ( notNullValue () ) );
84- assertThat ( batchFetchQueue . getSubselect ( key3 ), is ( notNullValue () ) );
85-
86- return in ;
87+ void testLazySubselectFetchingFromFind (final SessionFactoryScope scope ) {
88+ scope .inTransaction ( session -> {
89+ session . enableFetchProfile ( "lazysubselect" );
90+
91+ final LazySelectRoot root = session .find ( LazySelectRoot . class , 1 );
92+
93+ assertNotInitialized ( root );
94+ Hibernate . initialize ( root . nodes );
95+
96+ assertGeneratedSubselects ( session );
97+ assertNodesInitialized ( root );
98+
99+ final LazySelectNode anyNode = root . nodes . iterator (). next ( );
100+ Hibernate . initialize ( anyNode . children );
101+
102+ assertFullyInitialized ( root ) ;
87103 } );
104+ }
88105
89- for ( final LazySelectNode node : root .nodes ) {
90- assertThat ( Hibernate .isInitialized ( ( (LazySelectNode ) Hibernate .unproxy ( node ) ).children ),
91- is ( false )
92- );
93- }
106+ @ Test
107+ void testEagerSubselectFetchingFromFind (final SessionFactoryScope scope ) {
108+ scope .inTransaction ( session -> {
109+ session .enableFetchProfile ( "eagersubselect" );
110+
111+ final LazySelectRoot root = session .find ( LazySelectRoot .class , 1 );
112+
113+ assertGeneratedSubselects ( session );
114+ assertFullyInitialized ( root );
115+ } );
116+ }
117+
118+ @ Test
119+ void testLazySubselectFetchingFromQuery (final SessionFactoryScope scope ) {
120+ scope .inTransaction ( session -> {
121+ session .enableFetchProfile ( "lazysubselect" );
122+
123+ final LazySelectRoot root = session .createQuery ( "select r from root r where r.id = ?1" ,
124+ LazySelectRoot .class )
125+ .setParameter ( 1 , 1 ).getSingleResult ();
126+
127+ assertNotInitialized ( root );
128+ Hibernate .initialize ( root .nodes );
129+
130+ assertGeneratedSubselects ( session );
131+ assertNodesInitialized ( root );
132+
133+ final LazySelectNode anyNode = root .nodes .iterator ().next ();
134+ Hibernate .initialize ( anyNode .children );
135+
136+ assertFullyInitialized ( root );
137+ } );
94138 }
95139
96140 @ Test
97- void testSubselectFetchingFromQuery (final EntityManagerFactoryScope scope ) {
98- final LazySelectRoot root = scope .fromTransaction ( em -> {
99- final SessionImplementor session = em .unwrap ( SessionImplementor .class );
100- final EntityPersister persister = session .getEntityPersister ( null , new LazySelectNode () );
101- final EntityKey key1 = session .generateEntityKey ( 10 , persister );
102- final EntityKey key2 = session .generateEntityKey ( 20 , persister );
103- final EntityKey key3 = session .generateEntityKey ( 30 , persister );
104-
105- final LazySelectRoot in = em .createQuery ( "select r from root r join fetch r.nodes where r.id = ?1" ,
106- LazySelectRoot .class ).setParameter ( 1 , 1 ).getSingleResult ();
107-
108- final BatchFetchQueue batchFetchQueue = session .getPersistenceContextInternal ().getBatchFetchQueue ();
109- assertThat ( batchFetchQueue .getSubselect ( key1 ), is ( notNullValue () ) );
110- assertThat ( batchFetchQueue .getSubselect ( key2 ), is ( notNullValue () ) );
111- assertThat ( batchFetchQueue .getSubselect ( key3 ), is ( notNullValue () ) );
112- return in ;
141+ void testEagerSubselectFetchingFromQuery (final SessionFactoryScope scope ) {
142+ scope .inTransaction ( session -> {
143+ session .enableFetchProfile ( "eagersubselect" );
144+
145+ final LazySelectRoot root = session .createQuery ( "select r from root r where r.id = ?1" ,
146+ LazySelectRoot .class ).setParameter ( 1 , 1 ).getSingleResult ();
147+
148+ assertGeneratedSubselects ( session );
149+ assertFullyInitialized ( root );
113150 } );
151+ }
114152
115- for ( final LazySelectNode node : root .nodes ) {
116- assertThat ( Hibernate .isInitialized ( ( (LazySelectNode ) Hibernate .unproxy ( node ) ).children ),
117- is ( false )
118- );
153+ private void assertGeneratedSubselects (final SessionImplementor session ) {
154+ final BatchFetchQueue batchFetchQueue = session .getPersistenceContextInternal ().getBatchFetchQueue ();
155+ assertThat ( batchFetchQueue .getSubselect ( key1 ), is ( notNullValue () ) );
156+ assertThat ( batchFetchQueue .getSubselect ( key2 ), is ( notNullValue () ) );
157+ assertThat ( batchFetchQueue .getSubselect ( key3 ), is ( notNullValue () ) );
158+ }
159+
160+ private void assertNotInitialized (LazySelectRoot root ) {
161+ assertThat ( Hibernate .isInitialized ( root .getNodes () ), is ( false ) );
162+ }
163+
164+ private void assertNodesInitialized (LazySelectRoot root ) {
165+ assertThat ( Hibernate .isInitialized ( root .getNodes () ), is ( true ) );
166+
167+ for ( final LazySelectNode node : root .getNodes () ) {
168+ assertThat ( Hibernate .isInitialized ( node .getChildren () ), is ( false ) );
169+ }
170+ }
171+
172+ private void assertFullyInitialized (LazySelectRoot root ) {
173+ assertThat ( Hibernate .isInitialized ( root .getNodes () ), is ( true ) );
174+
175+ for ( final LazySelectNode node : root .getNodes () ) {
176+ assertThat ( Hibernate .isInitialized ( node .getChildren () ), is ( true ) );
119177 }
120178 }
121179
122180 @ Entity (name = "root" )
181+ @ FetchProfile (name = "lazysubselect" )
182+ @ FetchProfile (name = "eagersubselect" )
123183 public static class LazySelectRoot {
124184 @ Id
125185 public Integer id ;
126186
127- @ OneToMany (cascade = CascadeType .ALL , fetch = FetchType .EAGER , mappedBy = "root" )
187+ @ OneToMany (cascade = CascadeType .ALL , mappedBy = "root" )
188+ @ FetchProfileOverride (profile = "lazysubselect" , fetch = FetchType .LAZY )
189+ @ FetchProfileOverride (profile = "eagersubselect" , fetch = FetchType .EAGER )
128190 public Set <LazySelectNode > nodes = new HashSet <>();
191+
192+ public Set <LazySelectNode > getNodes () {
193+ return nodes ;
194+ }
129195 }
130196
131197 @ Entity (name = "node" )
@@ -139,7 +205,12 @@ public static class LazySelectNode {
139205
140206 @ ManyToMany (cascade = CascadeType .ALL )
141207 @ JoinTable (name = "RELATIONSHIPS" )
142- @ Fetch (FetchMode .SUBSELECT )
208+ @ FetchProfileOverride (profile = "lazysubselect" , fetch = FetchType .LAZY , mode = FetchMode .SUBSELECT )
209+ @ FetchProfileOverride (profile = "eagersubselect" , fetch = FetchType .EAGER , mode = FetchMode .SUBSELECT )
143210 public final Set <LazySelectNode > children = new HashSet <>();
211+
212+ public Set <LazySelectNode > getChildren () {
213+ return children ;
214+ }
144215 }
145216}
0 commit comments