1 package ejava.jpa.examples.query.jpaql;
2
3 import static org.junit.Assert.*;
4
5 import java.math.BigDecimal;
6 import java.text.NumberFormat;
7 import java.util.Arrays;
8 import java.util.Date;
9 import java.util.HashMap;
10 import java.util.List;
11 import java.util.Map;
12 import java.util.Map.Entry;
13 import java.util.stream.Collectors;
14 import java.util.stream.Stream;
15
16 import javax.persistence.EntityManager;
17 import javax.persistence.Tuple;
18 import javax.persistence.TypedQuery;
19
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22 import org.hibernate.LazyInitializationException;
23 import org.junit.Test;
24
25 import ejava.jpa.examples.query.Clerk;
26 import ejava.jpa.examples.query.Customer;
27 import ejava.jpa.examples.query.QueryBase;
28 import ejava.jpa.examples.query.Receipt;
29 import ejava.jpa.examples.query.Sale;
30 import ejava.jpa.examples.query.Store;
31
32 public class JPAQLTest extends QueryBase {
33 private static final Logger logger = LoggerFactory.getLogger(BulkQueryTest.class);
34
35 private <T> List<T> executeQuery(String ejbqlString, Class<T> resultType) {
36 return executeQuery(ejbqlString, null, resultType);
37 }
38
39 private <T> List<T> executeQuery(String ejbqlString,
40 Map<String, Object> params, Class<T> resultType) {
41 TypedQuery<T> query = em.createQuery(ejbqlString, resultType);
42 logger.info("executing query: {}", ejbqlString);
43 if (params != null && !params.isEmpty()) {
44 StringBuilder text=new StringBuilder();
45 for(String key: params.keySet()) {
46 Object param = params.get(key);
47 text.append(key +"=" + param + ",");
48 query.setParameter(key, param);
49 }
50 logger.info(" with params:[{}]", text);
51 }
52 List<T> objects = query.getResultList();
53 for(Object o: objects) {
54 logger.info("found result:{}", o);
55 }
56 return objects;
57 }
58
59
60
61
62 @Test
63 public void testSimpleSelect() {
64 logger.info("*** testSimpleSelect() ***");
65
66 TypedQuery<Customer> query = em.createQuery(
67 "select object(c) from Customer as c",
68 Customer.class);
69 List<Customer> results = query.getResultList();
70 for (Customer result : results) {
71 logger.info("found={}", result);
72 }
73 int rows = results.size();
74 assertTrue("unexpected number of customers", rows > 0);
75 }
76
77
78
79
80 @Test
81 public void testResultStream() {
82 logger.info("*** testStream() ***");
83 TypedQuery<Customer> query = em.createQuery(
84 "select c from Customer as c",
85 Customer.class);
86
87 Stream<Customer> s = query.getResultStream();
88 Map<String, Customer> resultMap = s.collect(
89 Collectors.toMap(c->c.getFirstName()+c.getLastName(), c->c ));
90
91 for (Entry<String, Customer> result : resultMap.entrySet()) {
92 logger.info("found={}", result);
93 }
94 int rows = resultMap.size();
95 assertTrue("unexpected number of customers", rows > 0);
96
97 }
98
99
100
101
102
103
104 @Test
105 public void testNonEntityQuery() {
106 logger.info("*** testNonEntityQuery() ***");
107
108 TypedQuery<String> query = em.createQuery(
109 "select c.lastName from Customer c", String.class);
110 List<String> results = query.getResultList();
111 assertTrue("no results", results.size() > 0);
112 for(String result : results) {
113 logger.info("lastName={}", result);
114 }
115 }
116
117
118
119
120
121 @Test
122 public void testMultiSelectObjectArray() {
123 logger.info("*** testMultiSelectObjectArray() ***");
124
125 TypedQuery<Object[]> query = em.createQuery(
126 "select c.firstName, c.hireDate from Clerk c", Object[].class);
127 List<Object[]> results = query.getResultList();
128 assertTrue("no results", results.size() > 0);
129 for(Object[] result : results) {
130 assertEquals("unexpected result length", 2, result.length);
131 String firstName = (String) result[0];
132 Date hireDate = (Date) result[1];
133 logger.info("firstName={} hireDate={}", firstName, hireDate);
134 }
135 }
136
137
138
139
140
141 @Test
142 public void testMultiSelectTuple() {
143 logger.info("*** testMultiSelectTuple() ***");
144
145 TypedQuery<Tuple> query = em.createQuery(
146 "select c.firstName as firstName, c.hireDate as hireDate from Clerk c", Tuple.class);
147 List<Tuple> results = query.getResultList();
148 assertTrue("no results", results.size() > 0);
149 for(Tuple result : results) {
150 assertEquals("unexpected result length", 2, result.getElements().size());
151 String firstName = result.get("firstName", String.class);
152 Date hireDate = result.get("hireDate", Date.class);
153 logger.info("firstName={} hireDate={}", firstName, hireDate);
154 }
155 }
156
157
158
159
160
161
162 @Test
163 public void testMultiSelectConstructor() {
164 logger.info("*** testMultiSelectConstructor() ***");
165
166 TypedQuery<Receipt> query = em.createQuery(
167 String.format("select new %s(", Receipt.class.getName()) +
168 "s.id,s.buyerId,s.date, s.amount) " +
169 "from Sale s", Receipt.class);
170 List<Receipt> results = query.getResultList();
171 assertTrue("no results", results.size() > 0);
172 for(Receipt receipt : results) {
173 assertNotNull("no receipt", receipt);
174 logger.info("receipt={}", receipt);
175 }
176 }
177
178
179
180
181
182 @Test
183 public void testPathExpressions() {
184 logger.info("*** testPathExpressions() ***");
185
186 TypedQuery<Object[]> query = em.createQuery(
187 "select s.id, s.store.name from Sale s", Object[].class);
188 List<Object[]> results = query.getResultList();
189 assertTrue("no results", results.size() > 0);
190 for(Object[] result : results) {
191 assertEquals("unexpected result length", 2, result.length);
192 Long id = (Long) result[0];
193 String name = (String) result[1];
194 logger.info("sale.id={}, sale.store.name={}", id, name);
195 }
196 }
197
198
199
200
201 @Test
202 public void testCollectionPathExpressionsInnerJoin() {
203 logger.info("*** testCollectionPathExpressionsInnerJoin ***");
204
205 int rows = executeQuery(
206
207
208 "select sale.date from Clerk c JOIN c.sales sale",
209 Date.class).size();
210 assertTrue("unexpected number of sales", rows > 0);
211 }
212
213
214
215
216 @Test
217 public void testOuterJoin() {
218 logger.info("*** testOuterJoin() ***");
219
220 TypedQuery<Object[]> query = em.createQuery(
221 "select c.id, c.firstName, sale.amount " +
222 "from Clerk c " +
223
224 "LEFT JOIN c.sales sale",
225 Object[].class);
226 List<Object[]> results = query.getResultList();
227 assertTrue("no results", results.size() > 0);
228 for(Object[] result : results) {
229 assertEquals("unexpected result length", 3, result.length);
230 Long id = (Long) result[0];
231 String name = (String) result[1];
232 BigDecimal amount = (BigDecimal) result[2];
233 logger.info("clerk.id={}, clerk.firstName={}, amount={}",
234 id, name, amount);
235 }
236 }
237
238
239
240
241 @Test
242 public void testExplicitJoin() {
243 logger.info("*** testExplicitJoin ***");
244
245 int rows = executeQuery(
246 "select c from Sale s, Customer c " +
247 "where c.id = s.buyerId",
248 Customer.class).size();
249 assertTrue("unexpected number of customers", rows > 0);
250 }
251
252
253
254
255
256
257 @Test
258 public void testFetchJoin1() {
259 logger.info("** testFetchJoin1() ***");
260 EntityManager em2 = createEm();
261 Store store = em2.createQuery(
262 "select s from Store s JOIN s.sales " +
263 "where s.name='Big Al''s'",
264 Store.class).getSingleResult();
265 logger.info("em.contains({})", em2.contains(store));
266 em2.close();
267 try {
268 store.getSales().get(0).getAmount();
269 fail("did not trigger lazy initialization exception");
270 } catch (LazyInitializationException expected) {
271 logger.info("caught expected exception:" + expected);
272 }
273 }
274 @Test
275 public void testFetchJoin2() {
276 logger.info("** testFetchJoin2() ***");
277 EntityManager em2 = createEm();
278 Store store = em2.createQuery(
279 "select s from Store s JOIN FETCH s.sales " +
280 "where s.name='Big Al''s'",
281 Store.class).getSingleResult();
282 logger.info("em.contains({})", em2.contains(store));
283 em2.close();
284 store.getSales().get(0).getAmount();
285 }
286
287
288
289
290
291 @Test
292 public void testMultiSelectEntities() {
293 logger.info("** testMultiSelectEntities() ***");
294
295 EntityManager em2 = createEm();
296 Sale sale = em2.createQuery(
297 "select sa as sale " +
298 "from Sale sa " +
299 "join sa.store st " +
300 "join sa.clerks c " +
301 "join fetch sa.clerks " +
302 "join fetch sa.store " +
303 "where st.name='Big Al''s' " +
304 "and sa member of c.sales",
305 Tuple.class).getResultList().get(0).get("sale", Sale.class);
306 em2.close();
307 sale.getAmount();
308 sale.getClerks().get(0).getFirstName();
309 sale.getStore();
310 }
311
312
313
314
315
316 @Test
317 public void testDISTINCT() {
318 logger.info("*** testDISTINCT() ***");
319
320 int rows = executeQuery(
321 "select DISTINCT c.lastName from Customer c",
322 Object[].class).size();
323 assertEquals("unexpected number of rows", 3, rows);
324 rows = executeQuery(
325 "select DISTINCT c.firstName from Customer c",
326 Object[].class).size();
327 assertEquals("unexpected number of rows for DISTINCT", 2, rows);
328 }
329
330
331
332
333
334
335
336
337 @Test
338 public void testLiteral() {
339 logger.info("*** testLiteral() ***");
340 int rows = executeQuery(
341 "select c from Customer c " +
342 "where c.firstName='cat'",
343 Customer.class).size();
344 assertEquals("unexpected number of rows:", 1, rows);
345 }
346
347 @Test
348 public void testSpecialCharacter() {
349 logger.info("*** testSpecialCharacter() ***");
350 int rows = executeQuery(
351 "select s from Store s " +
352 "where s.name='Big Al''s'",
353 Store.class).size();
354 assertEquals("unexpected number of rows", 1, rows);
355 }
356
357
358
359
360 @Test
361 public void testLike() {
362 logger.info("*** testLike() ***");
363
364 int rows = executeQuery(
365 "select c from Clerk c " +
366 "where c.firstName like 'M%'",
367 Clerk.class).size();
368 assertEquals("unexpected number of rows", 2, rows);
369
370 Map<String,Object> params = new HashMap<String, Object>();
371 params.put("firstName", "M%");
372 rows = executeQuery(
373 "select c from Clerk c " +
374 "where c.firstName like :firstName",
375 params,Clerk.class).size();
376 assertEquals("unexpected number of rows", 2, rows);
377
378 params = new HashMap<String, Object>();
379 params.put("firstName", "M");
380 rows = executeQuery(
381 "select c from Clerk c " +
382 "where c.firstName like concat(:firstName,'%')",
383 params, Clerk.class).size();
384 assertEquals("unexpected number of rows", 2, rows);
385
386 rows = executeQuery(
387 "select c from Clerk c " +
388 "where c.firstName like '_anny'",
389 Clerk.class).size();
390 assertEquals("unexpected number of rows", 1, rows);
391
392 }
393
394
395
396
397
398 @Test
399 public void testFormulas() {
400 logger.info("*** testFormulas() ***");
401
402 String jpaql = "select count(s) from Sale s " +
403 "where (s.amount * :tax) > :amount";
404 TypedQuery<Number> query = em.createQuery(jpaql, Number.class)
405 .setParameter("amount", new BigDecimal(10.00));
406
407
408 double tax = 0.05;
409 for (;query.setParameter("tax", new BigDecimal(tax))
410 .getSingleResult().intValue()==0;
411 tax += 0.01) {
412 logger.debug("tax={}", NumberFormat.getPercentInstance().format(tax));
413 }
414 logger.info("raise taxes to: {}", NumberFormat.getPercentInstance().format(tax));
415
416 assertEquals("unexpected level for tax:" + tax, 0.07, tax, .01);
417 }
418
419
420
421
422
423 @Test
424 public void testLogical() {
425 logger.info("*** testLogical() ***");
426 int rows = executeQuery(
427 "select c from Customer c " +
428 "where (c.firstName='cat' AND c.lastName='inhat')" +
429 "OR c.firstName='thing'",
430 Customer.class).size();
431 assertEquals("unexpected number of rows", 3, rows);
432
433 rows = executeQuery(
434 "select c from Customer c " +
435 "where (NOT (c.firstName='cat' AND c.lastName='inhat')) " +
436 "OR c.firstName='thing'",
437 Customer.class).size();
438 assertEquals("unexpected number of rows", 2, rows);
439 }
440
441
442
443
444
445 @Test
446 public void testEquality() {
447 logger.info("*** testEquality() ***");
448
449
450 Clerk clerk = em.createQuery(
451 "select c from Clerk c where c.firstName = 'Manny'",
452 Clerk.class)
453 .getSingleResult();
454
455
456 List<Sale> sales = em.createQuery(
457 "select s from Sale s " +
458 "JOIN s.clerks c " +
459 "where c = :clerk",
460 Sale.class)
461 .setParameter("clerk", clerk)
462 .getResultList();
463
464 for (Sale result : sales) {
465 logger.info("found={}", result);
466 }
467 assertEquals("unexpected number of rows", 2, sales.size());
468 }
469
470
471
472
473 @Test
474 public void testBetween() {
475 logger.info("*** testBetween() ***");
476
477 String query = "select s from Sale s " +
478 "where s.amount BETWEEN :low AND :high";
479 Map<String, Object> params = new HashMap<String, Object>();
480 params.put("low", new BigDecimal(90.00));
481 params.put("high", new BigDecimal(110.00));
482
483 int rows = executeQuery(query, params, Sale.class).size();
484 assertEquals("unexpected number of rows", 1, rows);
485
486 query = "select s from Sale s " +
487 "where s.amount NOT BETWEEN :low AND :high";
488 params = new HashMap<String, Object>();
489 params.put("low", new BigDecimal(90.00));
490 params.put("high", new BigDecimal(110.00));
491
492 rows = executeQuery(query, params, Sale.class).size();
493 assertEquals("unexpected number of rows", 1, rows);
494 }
495
496
497
498
499 @Test
500 public void testIsNull() {
501 logger.info("*** testIsNull() ***");
502
503 String query = "select s from Sale s " +
504 "where s.store IS NULL";
505
506 int rows = executeQuery(query, Sale.class).size();
507 assertEquals("unexpected number of rows", 0, rows);
508
509 query = "select s from Sale s " +
510 "where s.store IS NOT NULL";
511
512 rows = executeQuery(query, Sale.class).size();
513 assertEquals("unexpected number of rows", 2, rows);
514 }
515
516
517
518
519
520 @Test
521 public void testIsEmpty() {
522 logger.info("*** testIsEmpty() ***");
523
524 String query = "select c from Clerk c " +
525 "where c.sales IS EMPTY";
526
527 int rows = executeQuery(query, Clerk.class).size();
528 assertEquals("unexpected number of rows", 1, rows);
529
530 query = "select c from Clerk c " +
531 "where c.sales IS NOT EMPTY";
532
533 rows = executeQuery(query, Clerk.class).size();
534 assertEquals("unexpected number of rows", 2, rows);
535 }
536
537
538
539
540
541 @Test
542 public void testMemberOf() {
543 logger.info("*** testMemberOf() ***");
544
545
546 Clerk clerk = em.createQuery(
547 "select c from Clerk c where c.firstName = 'Manny'",
548 Clerk.class)
549 .getSingleResult();
550
551
552 List<Sale> sales = em.createQuery(
553 "select s from Sale s " +
554 "where :clerk MEMBER OF s.clerks", Sale.class)
555 .setParameter("clerk", clerk)
556 .getResultList();
557
558 for (Sale result : sales) {
559 logger.info("found={}", result);
560 }
561 assertEquals("unexpected number of rows", 2, sales.size());
562 }
563
564
565
566
567 @Test
568 public void testSubqueries() {
569 logger.info("*** testSubqueries() ***");
570
571 List<Customer> results = executeQuery(
572 "select c from Customer c " +
573 "where c.id IN " +
574 "(select s.buyerId from Sale s " +
575 "where s.amount > 100)",
576 Customer.class);
577 assertEquals("unexpected number of rows", 1, results.size());
578 }
579
580
581
582
583
584
585 @Test
586 public void testAll() {
587 logger.info("*** testAll() ***");
588
589
590
591 List<Clerk> results = executeQuery(
592 "select c from Clerk c " +
593 "where 125 < ALL " +
594 " (select s.amount from c.sales s)",
595 Clerk.class);
596 assertEquals("unexpected number of rows", 2, results.size());
597
598 results = executeQuery(
599 "select c from Clerk c " +
600 "where 125 > ALL " +
601 " (select s.amount from c.sales s)",
602 Clerk.class);
603 assertEquals("unexpected number of rows", 1, results.size());
604 }
605
606
607
608
609
610 @Test
611 public void testAny() {
612 List<Clerk> results = executeQuery(
613 "select c from Clerk c " +
614 "where 125 < ANY " +
615 " (select s.amount from c.sales s)",
616 Clerk.class);
617 assertEquals("unexpected number of rows", 2, results.size());
618
619 results = executeQuery(
620 "select c from Clerk c " +
621 "where 125 > ANY " +
622 " (select s.amount from c.sales s)",
623 Clerk.class);
624 assertEquals("unexpected number of rows", 1, results.size());
625 }
626
627
628
629
630
631
632 @Test
633 public void testStringFunctions() {
634 logger.info("*** testStringFunctions() ***");
635
636 int rows = executeQuery(
637 "select c from Customer c " +
638 "where c.firstName='CAT'",
639 Customer.class).size();
640 assertEquals("unexpected number of rows", 0, rows);
641
642 rows = executeQuery(
643 "select c from Customer c " +
644 "where c.firstName=LOWER('CAT')",
645 Customer.class).size();
646 assertEquals("unexpected number of rows", 1, rows);
647
648 rows = executeQuery(
649 "select UPPER(c.firstName) from Customer c " +
650 "where c.firstName=LOWER('CAT')",
651 String.class).size();
652 assertEquals("unexpected number of rows", 1, rows);
653
654 rows = executeQuery(
655 "select TRIM(LEADING 'c' FROM c.firstName) from Customer c " +
656 "where c.firstName='cat'",
657 String.class).size();
658 assertEquals("unexpected number of rows", 1, rows);
659
660 rows = executeQuery(
661 "select c from Customer c " +
662 "where CONCAT(CONCAT(c.firstName,' '),c.lastName) ='cat inhat'",
663 Customer.class).size();
664 assertEquals("unexpected number of rows", 1, rows);
665
666 rows = executeQuery(
667 "select c from Customer c " +
668 "where LENGTH(c.firstName) = 3",
669 Customer.class).size();
670 assertEquals("unexpected number of rows", 1, rows);
671
672 rows = executeQuery(
673 "select c from Customer c " +
674 "where LOCATE('cat',c.firstName,2) > 0",
675 Customer.class).size();
676 assertEquals("unexpected number of rows", 0, rows);
677
678 rows = executeQuery(
679 "select c from Customer c " +
680 "where LOCATE('at',c.firstName,2) > 1",
681 Customer.class).size();
682 assertEquals("unexpected number of rows", 1, rows);
683
684 rows = executeQuery(
685 "select SUBSTRING(c.firstName,2,2) from Customer c " +
686 "where c.firstName = 'cat'",
687 String.class).size();
688 assertEquals("unexpected number of rows", 1, rows);
689
690 rows = executeQuery(
691 "select c from Customer c " +
692 "where SUBSTRING(c.firstName,2,2) = 'at'",
693 Customer.class).size();
694 assertEquals("unexpected number of rows", 1, rows);
695 }
696
697
698
699
700 @Test
701 public void testDates() {
702 logger.info("*** testDates() ***");
703
704 int rows = executeQuery(
705 "select s from Sale s " +
706 "where s.date < CURRENT_DATE",
707 Sale.class).size();
708 assertEquals("unexpected number of rows", 2, rows);
709
710 rows = executeQuery(
711 "select s from Sale s " +
712 "where s.date = CURRENT_DATE",
713 Sale.class).size();
714 assertEquals("unexpected number of rows", 0, rows);
715
716 rows = em.createQuery(
717 "update Sale s " +
718 "set s.date = CURRENT_DATE").executeUpdate();
719 assertEquals("unexpected number of rows", 2, rows);
720
721 em.getTransaction().commit();
722 em.clear();
723
724 rows = executeQuery(
725 "select s from Sale s " +
726 "where s.date = CURRENT_DATE",
727 Sale.class).size();
728 assertEquals("unexpected number of rows", 2, rows);
729 }
730
731
732
733
734
735 @Test
736 public void testOrderBy() {
737 logger.info("*** testOrderBy() ***");
738
739 List<Sale> results = executeQuery(
740 "select s from Sale s ORDER BY s.amount ASC", Sale.class);
741 assertEquals("unexpected number of rows", 2, results.size());
742 assertEquals("unexpected first element",
743 100,
744 results.get(0).getAmount().intValue());
745 assertEquals("unexpected first element",
746 150,
747 results.get(1).getAmount().intValue());
748
749
750 results = executeQuery(
751 "select s from Sale s ORDER BY s.amount DESC", Sale.class);
752 assertEquals("unexpected number of rows", 2, results.size());
753 assertEquals("unexpected first element",
754 150,
755 results.get(0).getAmount().intValue());
756 assertEquals("unexpected first element",
757 100,
758 results.get(1).getAmount().intValue());
759 }
760
761
762
763
764
765 @Test
766 public void testCount() {
767 logger.info("*** testCount() ***");
768
769 List<Number> results= executeQuery(
770 "select COUNT(s) from Sale s", Number.class);
771 assertEquals("unexpected number of rows", 1, results.size());
772 assertEquals("unexpected result", 2, results.get(0).intValue());
773 }
774
775
776
777
778 @Test
779 public void testMaxMin() {
780 logger.info("*** testMaxMin() ***");
781
782 List<Number> results= executeQuery(
783 "select max(s.amount) from Sale s", Number.class);
784 assertEquals("unexpected number of rows", 1, results.size());
785 assertEquals("unexpected result", 150, results.get(0).intValue());
786
787 results= executeQuery(
788 "select min(s.amount) from Sale s", Number.class);
789 assertEquals("unexpected number of rows", 1, results.size());
790 assertEquals("unexpected result", 100, results.get(0).intValue());
791 }
792
793
794
795
796 @Test
797 public void testSumAve() {
798 logger.info("*** testSumAve() ***");
799
800 List<Number> results= executeQuery(
801 "select sum(s.amount) from Sale s", Number.class);
802 assertEquals("unexpected number of rows", 1, results.size());
803 assertEquals("unexpected result", 250, results.get(0).intValue());
804
805 results= executeQuery(
806 "select avg(s.amount) from Sale s", Number.class);
807 assertEquals("unexpected number of rows", 1, results.size());
808 assertEquals("unexpected result", 125, results.get(0).intValue());
809 }
810
811
812
813
814 @Test
815 public void testGroupBy() {
816 logger.info("*** testGroupBy() ***");
817
818 List<Object[]> results= em.createQuery(
819 "select c, COUNT(s) from Clerk c " +
820 "LEFT JOIN c.sales s " +
821 "GROUP BY c", Object[].class)
822 .getResultList();
823 for (Object[] result : results) {
824 logger.info("found={}", Arrays.toString(result));
825 }
826 assertEquals("unexpected number of rows", 3, results.size());
827 }
828
829
830
831
832
833
834 @Test
835 public void testHaving() {
836 logger.info("*** testHaving() ***");
837
838 List<Object[]> results= em.createQuery(
839 "select c, COUNT(s) from Clerk c " +
840 "LEFT JOIN c.sales s " +
841 "GROUP BY c " +
842 "HAVING COUNT(s) <= 1", Object[].class)
843 .getResultList();
844 for (Object[] result : results) {
845 logger.info("found={}", Arrays.toString(result));
846 }
847 assertEquals("unexpected number of rows", 2, results.size());
848 }
849 }