28
28
import org .hibernate .testing .orm .junit .Jira ;
29
29
import org .hibernate .testing .orm .junit .Jpa ;
30
30
import org .hibernate .testing .orm .junit .RequiresDialect ;
31
+ import org .hibernate .testing .orm .junit .SessionFactoryScope ;
31
32
import org .junit .jupiter .api .AfterAll ;
33
+ import org .junit .jupiter .api .AfterEach ;
34
+ import org .junit .jupiter .api .Assertions ;
32
35
import org .junit .jupiter .api .BeforeAll ;
36
+ import org .junit .jupiter .api .BeforeEach ;
33
37
import org .junit .jupiter .api .Test ;
34
38
39
+ import jakarta .persistence .Column ;
35
40
import jakarta .persistence .Entity ;
36
41
import jakarta .persistence .Id ;
37
42
import jakarta .persistence .NamedStoredProcedureQueries ;
38
43
import jakarta .persistence .NamedStoredProcedureQuery ;
39
44
import jakarta .persistence .ParameterMode ;
40
45
import jakarta .persistence .StoredProcedureParameter ;
41
46
import jakarta .persistence .StoredProcedureQuery ;
47
+ import jakarta .persistence .Table ;
48
+ import org .hamcrest .MatcherAssert ;
42
49
43
50
import static org .assertj .core .api .Assertions .assertThat ;
51
+ import static org .hamcrest .core .Is .is ;
44
52
import static org .junit .jupiter .api .Assertions .assertEquals ;
45
53
import static org .junit .jupiter .api .Assertions .assertFalse ;
46
54
import static org .junit .jupiter .api .Assertions .assertNotNull ;
55
63
Phone .class ,
56
64
Vote .class ,
57
65
DB2StoredProcedureTest .IdHolder .class ,
66
+ DB2StoredProcedureTest .Address .class ,
58
67
} )
59
68
@ RequiresDialect ( value = DB2Dialect .class )
60
69
@ Jira ( "https://hibernate.atlassian.net/browse/HHH-18332" )
61
70
public class DB2StoredProcedureTest {
71
+
72
+ private static final String CITY = "London" ;
73
+ private static final String STREET = "Lollard Street" ;
74
+ private static final String ZIP = "SE116U" ;
75
+
62
76
@ Test
63
77
public void testStoredProcedureOutParameter (EntityManagerFactoryScope scope ) {
64
78
scope .inTransaction ( entityManager -> {
@@ -242,6 +256,88 @@ public void testBindParameterAsHibernateType(EntityManagerFactoryScope scope) {
242
256
} );
243
257
}
244
258
259
+ @ Test
260
+ @ Jira ( "https://hibernate.atlassian.net/browse/HHH-18302" )
261
+ public void testStoredProcedureInAndOutAndRefCursorParameters (EntityManagerFactoryScope scope ) {
262
+ scope .inTransaction (
263
+ entityManager -> {
264
+ StoredProcedureQuery query = entityManager .createStoredProcedureQuery ( "sp_get_address_by_street_city" );
265
+ query .registerStoredProcedureParameter ( "street_in" , String .class , ParameterMode .IN );
266
+ query .registerStoredProcedureParameter ( "city_in" , String .class , ParameterMode .IN );
267
+ query .registerStoredProcedureParameter ( "rec_out" , ResultSet .class , ParameterMode .REF_CURSOR );
268
+
269
+ query .setParameter ( "street_in" , STREET )
270
+ .setParameter ( "city_in" , CITY );
271
+ query .execute ();
272
+ ResultSet rs = (ResultSet ) query .getOutputParameterValue ( "rec_out" );
273
+ try {
274
+ Assertions .assertTrue ( rs .next () );
275
+ MatcherAssert .assertThat ( rs .getString ( "street" ), is ( STREET ) );
276
+ MatcherAssert .assertThat ( rs .getString ( "city" ), is ( CITY ) );
277
+ MatcherAssert .assertThat ( rs .getString ( "zip" ), is ( ZIP ) );
278
+ }
279
+ catch (SQLException e ) {
280
+ throw new RuntimeException ( e );
281
+ }
282
+ }
283
+ );
284
+ }
285
+
286
+ @ Test
287
+ @ Jira ( "https://hibernate.atlassian.net/browse/HHH-18302" )
288
+ public void testStoredProcedureInAndOutAndRefCursorParametersDifferentRegistrationOrder (EntityManagerFactoryScope scope ) {
289
+ scope .inTransaction (
290
+ entityManager -> {
291
+ StoredProcedureQuery query = entityManager .createStoredProcedureQuery ( "sp_get_address_by_street_city" );
292
+ query .registerStoredProcedureParameter ( "city_in" , String .class , ParameterMode .IN );
293
+ query .registerStoredProcedureParameter ( "street_in" , String .class , ParameterMode .IN );
294
+ query .registerStoredProcedureParameter ( "rec_out" , ResultSet .class , ParameterMode .REF_CURSOR );
295
+
296
+ query .setParameter ( "street_in" , STREET )
297
+ .setParameter ( "city_in" , CITY );
298
+ query .execute ();
299
+ ResultSet rs = (ResultSet ) query .getOutputParameterValue ( "rec_out" );
300
+ try {
301
+ Assertions .assertTrue ( rs .next () );
302
+ MatcherAssert .assertThat ( rs .getString ( "street" ), is ( STREET ) );
303
+ MatcherAssert .assertThat ( rs .getString ( "city" ), is ( CITY ) );
304
+ MatcherAssert .assertThat ( rs .getString ( "zip" ), is ( ZIP ) );
305
+ }
306
+ catch (SQLException e ) {
307
+ throw new RuntimeException ( e );
308
+ }
309
+ }
310
+ );
311
+ }
312
+
313
+ @ Test
314
+ @ Jira ( "https://hibernate.atlassian.net/browse/HHH-18302" )
315
+ public void testStoredProcedureInAndOutAndRefCursorParametersDifferentRegistrationOrder2 (EntityManagerFactoryScope scope ) {
316
+ scope .inTransaction (
317
+ entityManager -> {
318
+ StoredProcedureQuery query = entityManager .createStoredProcedureQuery ( "sp_get_address_by_street_city" );
319
+ query .registerStoredProcedureParameter ( "rec_out" , ResultSet .class , ParameterMode .REF_CURSOR );
320
+ query .registerStoredProcedureParameter ( "city_in" , String .class , ParameterMode .IN );
321
+ query .registerStoredProcedureParameter ( "street_in" , String .class , ParameterMode .IN );
322
+
323
+ query .setParameter ( "street_in" , STREET )
324
+ .setParameter ( "city_in" , CITY );
325
+ query .execute ();
326
+ ResultSet rs = (ResultSet ) query .getOutputParameterValue ( "rec_out" );
327
+ try {
328
+ Assertions .assertTrue ( rs .next () );
329
+ MatcherAssert .assertThat ( rs .getString ( "street" ), is ( STREET ) );
330
+ MatcherAssert .assertThat ( rs .getString ( "city" ), is ( CITY ) );
331
+ MatcherAssert .assertThat ( rs .getString ( "zip" ), is ( ZIP ) );
332
+ }
333
+ catch (SQLException e ) {
334
+ throw new RuntimeException ( e );
335
+ }
336
+ }
337
+ );
338
+ }
339
+
340
+
245
341
@ BeforeAll
246
342
public void prepareSchema (EntityManagerFactoryScope scope ) {
247
343
scope .inTransaction ( (entityManager ) -> entityManager .unwrap ( Session .class ).doWork ( (connection ) -> {
@@ -355,9 +451,27 @@ public void prepareSchema(EntityManagerFactoryScope scope) {
355
451
" OPEN votes; " +
356
452
"END"
357
453
);
454
+ statement .executeUpdate (
455
+ "CREATE OR REPLACE PROCEDURE sp_get_address_by_street_city ( " +
456
+ " IN street_in VARCHAR(255), " +
457
+ " IN city_in VARCHAR(255), " +
458
+ " OUT rec_out CURSOR ) " +
459
+ "BEGIN " +
460
+ " SET rec_out = CURSOR FOR " +
461
+ " SELECT * " +
462
+ " FROM ADDRESS_TABLE A " +
463
+ " WHERE " +
464
+ " A.STREET = street_in" +
465
+ " AND A.CITY = city_in;" +
466
+ " OPEN rec_out; " +
467
+ "END;"
468
+ );
358
469
}
359
470
} ) );
471
+ }
360
472
473
+ @ BeforeEach
474
+ public void setUp (EntityManagerFactoryScope scope ){
361
475
scope .inTransaction ( (entityManager ) -> {
362
476
final Person person1 = new Person ( 1L , "John Doe" );
363
477
person1 .setNickName ( "JD" );
@@ -377,6 +491,8 @@ public void prepareSchema(EntityManagerFactoryScope scope) {
377
491
phone2 .setValid ( false );
378
492
379
493
person1 .addPhone ( phone2 );
494
+ Address address = new Address ( 1l , STREET , CITY , ZIP );
495
+ entityManager .persist ( address );
380
496
} );
381
497
}
382
498
@@ -394,15 +510,21 @@ public void cleanUpSchema(EntityManagerFactoryScope scope) {
394
510
statement .executeUpdate ( "DROP PROCEDURE outAndRefCursor" );
395
511
statement .executeUpdate ( "DROP PROCEDURE sp_phone_validity" );
396
512
statement .executeUpdate ( "DROP PROCEDURE sp_votes" );
513
+ statement .executeUpdate ( "DROP PROCEDURE sp_get_address_by_street_city" );
397
514
}
398
515
catch (final SQLException ignore ) {
399
516
}
400
517
} );
518
+ } );
519
+ }
401
520
402
- scope .inTransaction ( em , (em2 ) -> {
403
- final List <Person > people = em .createQuery ( "from Person" , Person .class ).getResultList ();
404
- people .forEach ( em ::remove );
405
- } );
521
+ @ AfterEach
522
+ public void cleanData (EntityManagerFactoryScope scope ) {
523
+ scope .inTransaction ( (em ) -> {
524
+ final List <Person > people = em .createQuery ( "from Person" , Person .class ).getResultList ();
525
+ people .forEach ( em ::remove );
526
+
527
+ em .createQuery ( "delete Address" ).executeUpdate ();
406
528
} );
407
529
}
408
530
@@ -429,4 +551,44 @@ public static class IdHolder {
429
551
Long id ;
430
552
String name ;
431
553
}
554
+
555
+ @ Entity (name = "Address" )
556
+ @ Table (name = "ADDRESS_TABLE" )
557
+ public static class Address {
558
+ @ Id
559
+ @ Column (name = "ID" )
560
+ private long id ;
561
+ @ Column (name = "STREET" )
562
+ private String street ;
563
+ @ Column (name = "CITY" )
564
+ private String city ;
565
+ @ Column (name = "ZIP" )
566
+ private String zip ;
567
+
568
+ public Address () {
569
+ }
570
+
571
+ public Address (long id , String street , String city , String zip ) {
572
+ this .id = id ;
573
+ this .street = street ;
574
+ this .city = city ;
575
+ this .zip = zip ;
576
+ }
577
+
578
+ public long getId () {
579
+ return id ;
580
+ }
581
+
582
+ public String getStreet () {
583
+ return street ;
584
+ }
585
+
586
+ public String getCity () {
587
+ return city ;
588
+ }
589
+
590
+ public String getZip () {
591
+ return zip ;
592
+ }
593
+ }
432
594
}
0 commit comments