44 */
55package org .hibernate .orm .test .stream .basic ;
66
7- import java .util .concurrent .atomic .AtomicInteger ;
8- import java .util .stream .Stream ;
9-
10- import org .hibernate .engine .spi .SessionImplementor ;
11-
12- import org .hibernate .testing .orm .junit .JiraKey ;
13- import org .hibernate .testing .orm .junit .DomainModel ;
14- import org .hibernate .testing .orm .junit .SessionFactory ;
15- import org .hibernate .testing .orm .junit .SessionFactoryScope ;
16- import org .junit .jupiter .api .Test ;
17-
187import jakarta .persistence .Entity ;
198import jakarta .persistence .Id ;
209import jakarta .persistence .Table ;
2110import jakarta .persistence .Tuple ;
2211import jakarta .persistence .criteria .CriteriaBuilder ;
2312import jakarta .persistence .criteria .CriteriaQuery ;
2413import jakarta .persistence .criteria .Root ;
14+ import org .hibernate .internal .util .MutableInteger ;
15+ import org .hibernate .query .spi .QueryImplementor ;
16+ import org .hibernate .testing .orm .junit .DomainModel ;
17+ import org .hibernate .testing .orm .junit .JiraKey ;
18+ import org .hibernate .testing .orm .junit .SessionFactory ;
19+ import org .hibernate .testing .orm .junit .SessionFactoryScope ;
20+ import org .junit .jupiter .api .AfterEach ;
21+ import org .junit .jupiter .api .BeforeEach ;
22+ import org .junit .jupiter .api .Test ;
23+
24+ import java .util .stream .Stream ;
2525
2626import static org .hamcrest .MatcherAssert .assertThat ;
2727import static org .hamcrest .core .Is .is ;
3131/**
3232 * @author Steve Ebersole
3333 */
34- @ DomainModel (
35- annotatedClasses = BasicStreamTest .MyEntity .class
36- )
34+ @ SuppressWarnings ("JUnitMalformedDeclaration" )
35+ @ DomainModel ( annotatedClasses = BasicStreamTest .MyEntity .class )
3736@ SessionFactory
3837public class BasicStreamTest {
3938
39+ @ BeforeEach
40+ void createTestData (SessionFactoryScope scope ) {
41+ scope .inTransaction ( (session ) -> {
42+ MyEntity e = new MyEntity ();
43+ e .id = 1 ;
44+ e .name = "Test" ;
45+ session .persist ( e );
46+ } );
47+ }
48+
49+ @ AfterEach
50+ void dropTestData (SessionFactoryScope scope ) {
51+ scope .dropData ();
52+ }
53+
4054 @ Test
41- public void basicStreamTest (SessionFactoryScope scope ) {
42-
43- scope .inTransaction (
44- session -> {
45- // mainly we want to make sure that closing the Stream releases the ScrollableResults too
46- assertThat ( ( (SessionImplementor ) session ).getJdbcCoordinator ()
47- .getLogicalConnection ()
48- .getResourceRegistry ()
49- .hasRegisteredResources (), is ( false ) );
50- final Stream <MyEntity > stream = session .createQuery ( "from MyEntity" , MyEntity .class ).stream ();
51- try {
52- stream .forEach ( System .out ::println );
53- assertThat ( session .getJdbcCoordinator ()
54- .getLogicalConnection ()
55- .getResourceRegistry ()
56- .hasRegisteredResources (), is ( true ) );
57- }
58- finally {
59- stream .close ();
60- assertThat ( session .getJdbcCoordinator ()
61- .getLogicalConnection ()
62- .getResourceRegistry ()
63- .hasRegisteredResources (), is ( false ) );
64- }
65-
66- }
67- );
55+ public void testBasicStreamHandling (SessionFactoryScope scope ) {
56+ // make sure that closing the Stream releases the ScrollableResults too
57+ scope .inTransaction ( (session ) -> {
58+ // at start, we should have no registered resources
59+ assertThat ( session .getJdbcCoordinator ()
60+ .getLogicalConnection ()
61+ .getResourceRegistry ()
62+ .hasRegisteredResources (), is ( false ) );
63+
64+ final Stream <MyEntity > stream = session .createQuery ( "from MyEntity" , MyEntity .class ).stream ();
65+ //noinspection TryFinallyCanBeTryWithResources
66+ try {
67+ stream .forEach ( System .out ::println );
68+ // we should have registered resources here as the underlying ScrollableResults is still open
69+ assertThat ( session .getJdbcCoordinator ()
70+ .getLogicalConnection ()
71+ .getResourceRegistry ()
72+ .hasRegisteredResources (), is ( true ) );
73+ }
74+ finally {
75+ stream .close ();
76+ // after an explicit close, we should have no registered resources
77+ assertThat ( session .getJdbcCoordinator ()
78+ .getLogicalConnection ()
79+ .getResourceRegistry ()
80+ .hasRegisteredResources (), is ( false ) );
81+ }
82+
83+ } );
6884 }
6985
7086 @ Test
71- @ JiraKey (value = "HHH-10824" )
72- public void testQueryStream (SessionFactoryScope scope ) {
73-
74- scope .inTransaction (
75- session -> {
76- MyEntity e = new MyEntity ();
77- e .id = 1 ;
78- e .name = "Test" ;
79- session .persist ( e );
80- }
81- );
82-
83- scope .inSession (
84- session -> {
85- // Test stream query without type.
86- try (Stream stream = session .createQuery ( "From MyEntity" ).stream ()) {
87- Object result = stream .findFirst ().orElse ( null );
88- assertTyping ( MyEntity .class , result );
89- }
90-
91- // Test stream query with type.
92- try (final Stream <MyEntity > stream = session .createQuery ( "From MyEntity" , MyEntity .class )
93- .stream ()) {
94- assertTyping ( MyEntity .class , stream .findFirst ().orElse ( null ) );
95- }
96-
97- // Test stream query using forEach
98- try (Stream <MyEntity > stream = session .createQuery ( "From MyEntity" , MyEntity .class )
99- .stream ()) {
100- stream .forEach ( i -> {
101- assertTyping ( MyEntity .class , i );
102- } );
103- }
104-
105- try (Stream <Object []> stream = session .createQuery ( "SELECT me.id, me.name FROM MyEntity me" )
106- .stream ()) {
107- stream .forEach ( i -> {
108- assertTyping ( Integer .class , i [0 ] );
109- assertTyping ( String .class , i [1 ] );
110- } );
111- }
112- }
113- );
87+ public void testStreamAutoClosing (SessionFactoryScope scope ) {
88+ // same as #testBasicStreamHandling but using try-with-resources
89+
90+ final MutableInteger onCloseCount = new MutableInteger ();
91+
92+ scope .inTransaction ( (session ) -> {
93+ // at start, we should have no registered resources
94+ assertThat ( session .getJdbcCoordinator ()
95+ .getLogicalConnection ()
96+ .getResourceRegistry ()
97+ .hasRegisteredResources (), is ( false ) );
98+ assertThat ( onCloseCount .get (), equalTo ( 0 ) );
99+
100+ final QueryImplementor <MyEntity > query = session .createQuery ( "from MyEntity" , MyEntity .class );
101+ try ( final Stream <MyEntity > stream = query .stream ().onClose ( onCloseCount ::increment ) ) {
102+ stream .forEach ( System .out ::println );
103+
104+ // we should have registered resources here as the underlying ScrollableResults is still open
105+ assertThat ( session .getJdbcCoordinator ()
106+ .getLogicalConnection ()
107+ .getResourceRegistry ()
108+ .hasRegisteredResources (), is ( true ) );
109+ assertThat ( onCloseCount .get (), equalTo ( 0 ) );
110+ }
111+
112+ assertThat ( session .getJdbcCoordinator ()
113+ .getLogicalConnection ()
114+ .getResourceRegistry ()
115+ .hasRegisteredResources (), is ( false ) );
114116
117+ assertThat ( onCloseCount .get (), equalTo ( 1 ) );
118+ } );
115119 }
116120
117121 @ Test
118- @ JiraKey (value = "HHH-11743" )
119- public void testTupleStream (SessionFactoryScope scope ) {
120- scope .inTransaction ( session -> {
121- MyEntity entity = new MyEntity ();
122- entity .id = 2 ;
123- entity .name = "an entity" ;
124- session .persist ( entity );
122+ @ JiraKey (value = "HHH-10824" )
123+ public void testQueryStreamTyping (SessionFactoryScope scope ) {
124+ // Test untyped query stream
125+ scope .inTransaction ( (session ) -> {
126+ try (Stream stream = session .createQuery ( "from MyEntity" ).stream ()) {
127+ Object result = stream .findFirst ().orElse ( null );
128+ assertTyping ( MyEntity .class , result );
129+ }
130+ } );
131+
132+ // Test typed query stream
133+ scope .inTransaction ( (session ) -> {
134+ try (final Stream <MyEntity > stream = session .createQuery ( "from MyEntity" , MyEntity .class ).stream ()) {
135+ assertTyping ( MyEntity .class , stream .findFirst ().orElse ( null ) );
136+ }
137+ } );
138+
139+ // Test stream query using forEach
140+ scope .inTransaction ( (session ) -> {
141+ try (Stream <MyEntity > stream = session .createQuery ( "from MyEntity" , MyEntity .class ).stream ()) {
142+ stream .forEach ( i -> {
143+ assertTyping ( MyEntity .class , i );
144+ } );
145+ }
146+ } );
147+
148+ // Test stream query with Object[] result
149+ scope .inTransaction ( (session ) -> {
150+ try (Stream <Object []> stream = session .createQuery ( "SELECT me.id, me.name from MyEntity me" ).stream ()) {
151+ stream .forEach ( i -> {
152+ assertTyping ( Integer .class , i [0 ] );
153+ assertTyping ( String .class , i [1 ] );
154+ } );
155+ }
125156 } );
126157
127158 //test tuple stream using criteria
@@ -144,45 +175,6 @@ public void testTupleStream(SessionFactoryScope scope) {
144175 } );
145176 }
146177
147- @ Test
148- public void basicStreamTestWithExplicitOnClose (SessionFactoryScope scope ) {
149- scope .inTransaction (
150- session -> {
151- AtomicInteger onCloseCount = new AtomicInteger ();
152-
153- // mainly we want to make sure that closing the Stream releases the ScrollableResults too
154- assertThat ( session .getJdbcCoordinator ()
155- .getLogicalConnection ()
156- .getResourceRegistry ()
157- .hasRegisteredResources (), is ( false ) );
158-
159- assertThat ( onCloseCount .get (), equalTo ( 0 ) );
160-
161- try (final Stream <MyEntity > stream = session .createQuery ( "from MyEntity" , MyEntity .class )
162- .stream ()
163- .onClose (
164- onCloseCount ::incrementAndGet )) {
165-
166-
167- assertThat ( onCloseCount .get (), equalTo ( 0 ) );
168-
169- stream .forEach ( System .out ::println );
170- assertThat ( session .getJdbcCoordinator ()
171- .getLogicalConnection ()
172- .getResourceRegistry ()
173- .hasRegisteredResources (), is ( true ) );
174- }
175-
176- assertThat ( session .getJdbcCoordinator ()
177- .getLogicalConnection ()
178- .getResourceRegistry ()
179- .hasRegisteredResources (), is ( false ) );
180-
181- assertThat ( onCloseCount .get (), equalTo ( 1 ) );
182- }
183- );
184- }
185-
186178 @ Entity (name = "MyEntity" )
187179 @ Table (name = "MyEntity" )
188180 public static class MyEntity {
0 commit comments