4
4
*/
5
5
package org .hibernate .orm .test .loading .multiLoad ;
6
6
7
+ import java .util .ArrayList ;
7
8
import java .util .List ;
8
9
import java .util .Objects ;
9
10
10
11
import org .hibernate .CacheMode ;
11
12
import org .hibernate .Hibernate ;
13
+ import org .hibernate .IncludeRemovals ;
14
+ import org .hibernate .OrderedReturn ;
15
+ import org .hibernate .SessionChecking ;
12
16
import org .hibernate .annotations .BatchSize ;
13
17
import org .hibernate .cache .spi .access .AccessType ;
14
18
import org .hibernate .cfg .AvailableSettings ;
37
41
import jakarta .persistence .Table ;
38
42
39
43
import static org .hamcrest .CoreMatchers .is ;
40
- import static org .junit . Assert . assertEquals ;
41
- import static org .junit .Assert . assertFalse ;
42
- import static org .junit .Assert . assertNotNull ;
43
- import static org .junit .Assert . assertNull ;
44
- import static org .junit .Assert . assertSame ;
45
- import static org .junit .Assert . assertThat ;
46
- import static org .junit .Assert .assertTrue ;
44
+ import static org .hamcrest . MatcherAssert . assertThat ;
45
+ import static org .junit .jupiter . api . Assertions . assertEquals ;
46
+ import static org .junit .jupiter . api . Assertions . assertFalse ;
47
+ import static org .junit .jupiter . api . Assertions . assertNotNull ;
48
+ import static org .junit .jupiter . api . Assertions . assertNull ;
49
+ import static org .junit .jupiter . api . Assertions . assertSame ;
50
+ import static org .junit .jupiter . api . Assertions .assertTrue ;
47
51
48
52
/**
49
53
* @author Steve Ebersole
@@ -86,7 +90,7 @@ public void testBasicMultiLoad(SessionFactoryScope scope) {
86
90
final SQLStatementInspector statementInspector = scope .getCollectingStatementInspector ();
87
91
scope .inTransaction (
88
92
session -> {
89
- statementInspector .getSqlQueries (). clear ();
93
+ statementInspector .clear ();
90
94
91
95
List <SimpleEntity > list = session .byMultipleIds ( SimpleEntity .class ).multiLoad ( ids ( 5 ) );
92
96
assertEquals ( 5 , list .size () );
@@ -218,6 +222,9 @@ public void testDuplicatedRequestedIdswithDisableOrderedReturn(SessionFactorySco
218
222
.enableOrderedReturn ( false )
219
223
.multiLoad ( 1 , 2 , 3 , 2 , 2 );
220
224
assertEquals ( 3 , list .size () );
225
+
226
+ list = session .findMultiple ( SimpleEntity .class , List .of ( 1 , 2 , 3 , 2 , 2 ), OrderedReturn .UNORDERED );
227
+ assertEquals ( 3 , list .size () );
221
228
}
222
229
);
223
230
}
@@ -235,6 +242,9 @@ public void testNonExistentIdRequest(SessionFactoryScope scope) {
235
242
// un-ordered multiLoad
236
243
list = session .byMultipleIds ( SimpleEntity .class ).enableOrderedReturn ( false ).multiLoad ( 1 , 699 , 2 );
237
244
assertEquals ( 2 , list .size () );
245
+
246
+ list = session .findMultiple ( SimpleEntity .class , List .of (1 , 699 , 2 ), OrderedReturn .UNORDERED );
247
+ assertEquals ( 2 , list .size () );
238
248
}
239
249
);
240
250
}
@@ -265,6 +275,12 @@ public void testBasicMultiLoadWithManagedAndChecking(SessionFactoryScope scope)
265
275
// this check is HIGHLY specific to implementation in the batch loader
266
276
// which puts existing managed entities first...
267
277
assertSame ( first , list .get ( 0 ) );
278
+
279
+ list = session .findMultiple ( SimpleEntity .class , idList (56 ), SessionChecking .ENABLED );
280
+ assertEquals ( 56 , list .size () );
281
+ // this check is HIGHLY specific to implementation in the batch loader
282
+ // which puts existing managed entities first...
283
+ assertSame ( first , list .get ( 0 ) );
268
284
}
269
285
);
270
286
}
@@ -295,6 +311,15 @@ public void testBasicMultiLoadWithManagedAndCheckingProxied(SessionFactoryScope
295
311
// this check is HIGHLY specific to implementation in the batch loader
296
312
// which puts existing managed entities first...
297
313
assertSame ( first , list .get ( 0 ) );
314
+
315
+ session .evict ( first );
316
+ first = session .byId ( SimpleEntity .class ).getReference ( 1 );
317
+
318
+ list = session .findMultiple ( SimpleEntity .class , idList (56 ), SessionChecking .ENABLED );
319
+ assertEquals ( 56 , list .size () );
320
+ // this check is HIGHLY specific to implementation in the batch loader
321
+ // which puts existing managed entities first...
322
+ assertSame ( first , list .get ( 0 ) );
298
323
}
299
324
);
300
325
}
@@ -330,7 +355,7 @@ public void testMultiLoadFrom2ndLevelCache(SessionFactoryScope scope) {
330
355
// Validate that the entity is still in the Level 2 cache
331
356
assertTrue ( session .getSessionFactory ().getCache ().containsEntity ( SimpleEntity .class , 2 ) );
332
357
333
- statementInspector .getSqlQueries (). clear ();
358
+ statementInspector .clear ();
334
359
335
360
// Multiload 3 items and ensure that multiload pulls 2 from the database & 1 from the cache.
336
361
List <SimpleEntity > entities = session .byMultipleIds ( SimpleEntity .class )
@@ -344,12 +369,37 @@ public void testMultiLoadFrom2ndLevelCache(SessionFactoryScope scope) {
344
369
assertTrue ( session .contains ( entity ) );
345
370
}
346
371
347
- final int paramCount = StringHelper .countUnquoted (
372
+ int paramCount = StringHelper .countUnquoted (
348
373
statementInspector .getSqlQueries ().get ( 0 ),
349
374
'?'
350
375
);
351
376
352
- final Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
377
+ Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
378
+ if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
379
+ assertThat ( paramCount , is ( 1 ) );
380
+ }
381
+ else {
382
+ assertThat ( paramCount , is ( 2 ) );
383
+ }
384
+
385
+ // Multiload 3 items and ensure that multiload pulls 2 from the database & 1 from the cache.
386
+ entities = session .findMultiple ( SimpleEntity .class , idList (3 ),
387
+ CacheMode .NORMAL ,
388
+ SessionChecking .ENABLED
389
+ );
390
+ assertEquals ( 3 , entities .size () );
391
+ assertEquals ( 1 , statistics .getSecondLevelCacheHitCount () );
392
+
393
+ for (SimpleEntity entity : entities ) {
394
+ assertTrue ( session .contains ( entity ) );
395
+ }
396
+
397
+ paramCount = StringHelper .countUnquoted (
398
+ statementInspector .getSqlQueries ().get ( 0 ),
399
+ '?'
400
+ );
401
+
402
+ dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
353
403
if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
354
404
assertThat ( paramCount , is ( 1 ) );
355
405
}
@@ -392,7 +442,7 @@ public void testUnorderedMultiLoadFrom2ndLevelCache(SessionFactoryScope scope) {
392
442
// Validate that the entity is still in the Level 2 cache
393
443
assertTrue ( session .getSessionFactory ().getCache ().containsEntity ( SimpleEntity .class , 2 ) );
394
444
395
- statementInspector .getSqlQueries (). clear ();
445
+ statementInspector .clear ();
396
446
397
447
// Multiload 3 items and ensure that multiload pulls 2 from the database & 1 from the cache.
398
448
List <SimpleEntity > entities = session .byMultipleIds ( SimpleEntity .class )
@@ -406,12 +456,37 @@ public void testUnorderedMultiLoadFrom2ndLevelCache(SessionFactoryScope scope) {
406
456
for ( SimpleEntity entity : entities ) {
407
457
assertTrue ( session .contains ( entity ) );
408
458
}
409
- final int paramCount = StringHelper .countUnquoted (
459
+ int paramCount = StringHelper .countUnquoted (
460
+ statementInspector .getSqlQueries ().get ( 0 ),
461
+ '?'
462
+ );
463
+
464
+ Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
465
+ if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
466
+ assertThat ( paramCount , is ( 1 ) );
467
+ }
468
+ else {
469
+ assertThat ( paramCount , is ( 2 ) );
470
+ }
471
+
472
+ // Multiload 3 items and ensure that multiload pulls 2 from the database & 1 from the cache.
473
+ entities = session .findMultiple ( SimpleEntity .class , idList (3 ),
474
+ CacheMode .NORMAL ,
475
+ SessionChecking .ENABLED ,
476
+ OrderedReturn .UNORDERED
477
+ );
478
+ assertEquals ( 3 , entities .size () );
479
+ assertEquals ( 1 , statistics .getSecondLevelCacheHitCount () );
480
+
481
+ for ( SimpleEntity entity : entities ) {
482
+ assertTrue ( session .contains ( entity ) );
483
+ }
484
+ paramCount = StringHelper .countUnquoted (
410
485
statementInspector .getSqlQueries ().get ( 0 ),
411
486
'?'
412
487
);
413
488
414
- final Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
489
+ dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
415
490
if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
416
491
assertThat ( paramCount , is ( 1 ) );
417
492
}
@@ -444,12 +519,35 @@ public void testOrderedMultiLoadFrom2ndLevelCachePendingDelete(SessionFactorySco
444
519
445
520
assertNull ( entities .get ( 1 ) );
446
521
447
- final int paramCount = StringHelper .countUnquoted (
522
+ int paramCount = StringHelper .countUnquoted (
448
523
statementInspector .getSqlQueries ().get ( 0 ),
449
524
'?'
450
525
);
451
526
452
- final Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
527
+ Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
528
+ if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
529
+ assertThat ( paramCount , is ( 1 ) );
530
+ }
531
+ else {
532
+ assertThat ( paramCount , is ( 2 ) );
533
+ }
534
+
535
+ // Multi-load 3 items and ensure that it pulls 2 from the database & 1 from the cache.
536
+ entities = session .findMultiple ( SimpleEntity .class , idList (3 ),
537
+ CacheMode .NORMAL ,
538
+ SessionChecking .ENABLED ,
539
+ OrderedReturn .ORDERED
540
+ );
541
+ assertEquals ( 3 , entities .size () );
542
+
543
+ assertNull ( entities .get ( 1 ) );
544
+
545
+ paramCount = StringHelper .countUnquoted (
546
+ statementInspector .getSqlQueries ().get ( 0 ),
547
+ '?'
548
+ );
549
+
550
+ dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
453
551
if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
454
552
assertThat ( paramCount , is ( 1 ) );
455
553
}
@@ -484,16 +582,45 @@ public void testOrderedMultiLoadFrom2ndLevelCachePendingDeleteReturnRemoved(Sess
484
582
SimpleEntity deletedEntity = entities .get ( 1 );
485
583
assertNotNull ( deletedEntity );
486
584
487
- final EntityEntry entry = session .getPersistenceContext ()
585
+ EntityEntry entry = session .getPersistenceContext ()
488
586
.getEntry ( deletedEntity );
489
587
assertTrue ( entry .getStatus ().isDeletedOrGone () );
490
588
491
- final int paramCount = StringHelper .countUnquoted (
589
+ int paramCount = StringHelper .countUnquoted (
590
+ statementInspector .getSqlQueries ().get ( 0 ),
591
+ '?'
592
+ );
593
+
594
+ Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
595
+ if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
596
+ assertThat ( paramCount , is ( 1 ) );
597
+ }
598
+ else {
599
+ assertThat ( paramCount , is ( 2 ) );
600
+ }
601
+
602
+ // Multiload 3 items and ensure that multiload pulls 2 from the database & 1 from the cache.
603
+ entities = session .findMultiple ( SimpleEntity .class , idList ( 3 ),
604
+ CacheMode .NORMAL ,
605
+ SessionChecking .ENABLED ,
606
+ OrderedReturn .ORDERED ,
607
+ IncludeRemovals .INCLUDE
608
+ );
609
+ assertEquals ( 3 , entities .size () );
610
+
611
+ deletedEntity = entities .get ( 1 );
612
+ assertNotNull ( deletedEntity );
613
+
614
+ entry = session .getPersistenceContext ()
615
+ .getEntry ( deletedEntity );
616
+ assertTrue ( entry .getStatus ().isDeletedOrGone () );
617
+
618
+ paramCount = StringHelper .countUnquoted (
492
619
statementInspector .getSqlQueries ().get ( 0 ),
493
620
'?'
494
621
);
495
622
496
- final Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
623
+ dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
497
624
if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
498
625
assertThat ( paramCount , is ( 1 ) );
499
626
}
@@ -525,12 +652,35 @@ public void testUnorderedMultiLoadFrom2ndLevelCachePendingDelete(SessionFactoryS
525
652
526
653
assertTrue ( entities .stream ().anyMatch ( Objects ::isNull ) );
527
654
528
- final int paramCount = StringHelper .countUnquoted (
655
+ int paramCount = StringHelper .countUnquoted (
656
+ statementInspector .getSqlQueries ().get ( 0 ),
657
+ '?'
658
+ );
659
+
660
+ Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
661
+ if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
662
+ assertThat ( paramCount , is ( 1 ) );
663
+ }
664
+ else {
665
+ assertThat ( paramCount , is ( 2 ) );
666
+ }
667
+
668
+ // Multiload 3 items and ensure that multiload pulls 2 from the database & 1 from the cache.
669
+ entities = session .findMultiple ( SimpleEntity .class , idList (3 ),
670
+ CacheMode .NORMAL ,
671
+ SessionChecking .ENABLED ,
672
+ OrderedReturn .UNORDERED
673
+ );
674
+ assertEquals ( 3 , entities .size () );
675
+
676
+ assertTrue ( entities .stream ().anyMatch ( Objects ::isNull ) );
677
+
678
+ paramCount = StringHelper .countUnquoted (
529
679
statementInspector .getSqlQueries ().get ( 0 ),
530
680
'?'
531
681
);
532
682
533
- final Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
683
+ dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
534
684
if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
535
685
assertThat ( paramCount , is ( 1 ) );
536
686
}
@@ -565,15 +715,44 @@ public void testUnorderedMultiLoadFrom2ndLevelCachePendingDeleteReturnRemoved(Se
565
715
.equals ( 2 ) ).findAny ().orElse ( null );
566
716
assertNotNull ( deletedEntity );
567
717
568
- final EntityEntry entry = session .getPersistenceContext ().getEntry ( deletedEntity );
718
+ EntityEntry entry = session .getPersistenceContext ().getEntry ( deletedEntity );
569
719
assertTrue ( entry .getStatus ().isDeletedOrGone () );
570
720
571
- final int paramCount = StringHelper .countUnquoted (
721
+ int paramCount = StringHelper .countUnquoted (
722
+ statementInspector .getSqlQueries ().get ( 0 ),
723
+ '?'
724
+ );
725
+
726
+ Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
727
+ if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
728
+ assertThat ( paramCount , is ( 1 ) );
729
+ }
730
+ else {
731
+ assertThat ( paramCount , is ( 2 ) );
732
+ }
733
+
734
+ // Multiload 3 items and ensure that multiload pulls 2 from the database & 1 from the cache.
735
+ entities = session .findMultiple ( SimpleEntity .class , idList (3 ),
736
+ CacheMode .NORMAL ,
737
+ SessionChecking .ENABLED ,
738
+ OrderedReturn .UNORDERED ,
739
+ IncludeRemovals .INCLUDE
740
+ );
741
+ assertEquals ( 3 , entities .size () );
742
+
743
+ deletedEntity = entities .stream ().filter ( simpleEntity -> simpleEntity .getId ()
744
+ .equals ( 2 ) ).findAny ().orElse ( null );
745
+ assertNotNull ( deletedEntity );
746
+
747
+ entry = session .getPersistenceContext ().getEntry ( deletedEntity );
748
+ assertTrue ( entry .getStatus ().isDeletedOrGone () );
749
+
750
+ paramCount = StringHelper .countUnquoted (
572
751
statementInspector .getSqlQueries ().get ( 0 ),
573
752
'?'
574
753
);
575
754
576
- final Dialect dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
755
+ dialect = session .getSessionFactory ().getJdbcServices ().getDialect ();
577
756
if ( MultiKeyLoadHelper .supportsSqlArrayType ( dialect ) ) {
578
757
assertThat ( paramCount , is ( 1 ) );
579
758
}
@@ -624,6 +803,12 @@ public void testMultiLoadClearsBatchFetchQueue(SessionFactoryScope scope) {
624
803
.getBatchFetchQueue ()
625
804
.containsEntityKey ( entityKey ) );
626
805
806
+ list = session .findMultiple ( SimpleEntity .class , idList (56 ), SessionChecking .ENABLED );
807
+
808
+ assertEquals ( 56 , list .size () );
809
+ assertFalse ( session .getPersistenceContext ()
810
+ .getBatchFetchQueue ()
811
+ .containsEntityKey ( entityKey ) );
627
812
}
628
813
);
629
814
}
@@ -636,6 +821,14 @@ private Integer[] ids(int count) {
636
821
return ids ;
637
822
}
638
823
824
+ private List <Integer > idList (int count ) {
825
+ List <Integer > ids = new ArrayList <>(count );
826
+ for ( int i = 1 ; i <= count ; i ++ ) {
827
+ ids .add (i );
828
+ }
829
+ return ids ;
830
+ }
831
+
639
832
@ Entity ( name = "SimpleEntity" )
640
833
@ Table ( name = "SimpleEntity" )
641
834
@ Cacheable ()
0 commit comments