0
# Query Execution
1
2
Complete reference for executing JPQL queries, native SQL queries, stored procedures, and named queries in Jakarta Persistence.
3
4
## Imports
5
6
```java { .api }
7
import jakarta.persistence.*;
8
```
9
10
## Capabilities
11
12
### Query Interface
13
14
Execute dynamic queries and control query execution.
15
16
```java { .api }
17
/**
18
* Base interface for executing queries
19
* @since 1.0
20
*/
21
public interface Query {
22
/**
23
* Execute a SELECT query and return the query results as a List
24
* @return list of results
25
*/
26
List getResultList();
27
28
/**
29
* Execute a SELECT query that returns a single result
30
* @return the result
31
* @throws NoResultException if no result
32
* @throws NonUniqueResultException if more than one result
33
*/
34
Object getSingleResult();
35
36
/**
37
* Execute an UPDATE or DELETE statement
38
* @return the number of entities updated or deleted
39
*/
40
int executeUpdate();
41
42
/**
43
* Execute a SELECT query and return results as a Stream
44
* @return a stream of the results
45
* @since 2.2
46
*/
47
Stream getResultStream();
48
49
/**
50
* Set the maximum number of results to retrieve
51
* @param maxResult maximum number of results
52
* @return the same query instance
53
*/
54
Query setMaxResults(int maxResult);
55
56
/**
57
* Get the maximum number of results to retrieve
58
* @return maximum number of results
59
* @since 2.0
60
*/
61
int getMaxResults();
62
63
/**
64
* Set the position of the first result to retrieve
65
* @param startPosition position of first result (numbered from 0)
66
* @return the same query instance
67
*/
68
Query setFirstResult(int startPosition);
69
70
/**
71
* Get the position of the first result
72
* @return position of first result
73
* @since 2.0
74
*/
75
int getFirstResult();
76
77
/**
78
* Set a query hint
79
* @param hintName hint name
80
* @param value hint value
81
* @return the same query instance
82
*/
83
Query setHint(String hintName, Object value);
84
85
/**
86
* Get the query hints
87
* @return query hints
88
* @since 2.0
89
*/
90
Map<String, Object> getHints();
91
92
/**
93
* Bind a value to a named parameter
94
* @param name parameter name
95
* @param value parameter value
96
* @return the same query instance
97
*/
98
<T> Query setParameter(String name, T value);
99
100
/**
101
* Bind a value to a positional parameter
102
* @param position parameter position (numbered from 1)
103
* @param value parameter value
104
* @return the same query instance
105
*/
106
Query setParameter(int position, Object value);
107
108
/**
109
* Bind a Calendar value to a named parameter
110
* @param name parameter name
111
* @param value parameter value
112
* @param temporalType temporal type
113
* @return the same query instance
114
*/
115
Query setParameter(String name, Calendar value, TemporalType temporalType);
116
117
/**
118
* Bind a Date value to a named parameter
119
* @param name parameter name
120
* @param value parameter value
121
* @param temporalType temporal type
122
* @return the same query instance
123
*/
124
Query setParameter(String name, Date value, TemporalType temporalType);
125
126
/**
127
* Bind a Calendar value to a positional parameter
128
* @param position parameter position
129
* @param value parameter value
130
* @param temporalType temporal type
131
* @return the same query instance
132
*/
133
Query setParameter(int position, Calendar value, TemporalType temporalType);
134
135
/**
136
* Bind a Date value to a positional parameter
137
* @param position parameter position
138
* @param value parameter value
139
* @param temporalType temporal type
140
* @return the same query instance
141
*/
142
Query setParameter(int position, Date value, TemporalType temporalType);
143
144
/**
145
* Bind a Parameter object
146
* @param param parameter object
147
* @param value parameter value
148
* @return the same query instance
149
* @since 2.0
150
*/
151
<T> Query setParameter(Parameter<T> param, T value);
152
153
/**
154
* Bind a Calendar Parameter
155
* @param param parameter object
156
* @param value parameter value
157
* @param temporalType temporal type
158
* @return the same query instance
159
* @since 2.0
160
*/
161
Query setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType);
162
163
/**
164
* Bind a Date Parameter
165
* @param param parameter object
166
* @param value parameter value
167
* @param temporalType temporal type
168
* @return the same query instance
169
* @since 2.0
170
*/
171
Query setParameter(Parameter<Date> param, Date value, TemporalType temporalType);
172
173
/**
174
* Get the parameters of the query
175
* @return parameters
176
* @since 2.0
177
*/
178
Set<Parameter<?>> getParameters();
179
180
/**
181
* Get the parameter object for a named parameter
182
* @param name parameter name
183
* @return parameter object
184
* @since 2.0
185
*/
186
Parameter<?> getParameter(String name);
187
188
/**
189
* Get a typed parameter object for a named parameter
190
* @param name parameter name
191
* @param type parameter type
192
* @return parameter object
193
* @since 2.0
194
*/
195
<T> Parameter<T> getParameter(String name, Class<T> type);
196
197
/**
198
* Get the parameter object for a positional parameter
199
* @param position parameter position
200
* @return parameter object
201
* @since 2.0
202
*/
203
Parameter<?> getParameter(int position);
204
205
/**
206
* Get a typed parameter object for a positional parameter
207
* @param position parameter position
208
* @param type parameter type
209
* @return parameter object
210
* @since 2.0
211
*/
212
<T> Parameter<T> getParameter(int position, Class<T> type);
213
214
/**
215
* Check if a parameter has been bound
216
* @param param parameter object
217
* @return true if bound
218
* @since 2.0
219
*/
220
boolean isBound(Parameter<?> param);
221
222
/**
223
* Get the value bound to a parameter
224
* @param param parameter object
225
* @return parameter value
226
* @since 2.0
227
*/
228
<T> T getParameterValue(Parameter<T> param);
229
230
/**
231
* Get the value bound to a named parameter
232
* @param name parameter name
233
* @return parameter value
234
* @since 2.0
235
*/
236
Object getParameterValue(String name);
237
238
/**
239
* Get the value bound to a positional parameter
240
* @param position parameter position
241
* @return parameter value
242
* @since 2.0
243
*/
244
Object getParameterValue(int position);
245
246
/**
247
* Set the flush mode for the query
248
* @param flushMode flush mode
249
* @return the same query instance
250
*/
251
Query setFlushMode(FlushModeType flushMode);
252
253
/**
254
* Get the flush mode for the query
255
* @return flush mode
256
* @since 2.0
257
*/
258
FlushModeType getFlushMode();
259
260
/**
261
* Set the lock mode for the query
262
* @param lockMode lock mode
263
* @return the same query instance
264
* @since 2.0
265
*/
266
Query setLockMode(LockModeType lockMode);
267
268
/**
269
* Get the lock mode for the query
270
* @return lock mode
271
* @since 2.0
272
*/
273
LockModeType getLockMode();
274
275
/**
276
* Return an object of the specified type to allow access to provider-specific API
277
* @param cls the class of the object to be returned
278
* @return an instance of the specified class
279
* @since 2.0
280
*/
281
<T> T unwrap(Class<T> cls);
282
}
283
284
/**
285
* Parameter interface for query parameters
286
* @since 2.0
287
*/
288
public interface Parameter<T> {
289
/**
290
* Get the parameter name, or null if not named
291
* @return parameter name
292
*/
293
String getName();
294
295
/**
296
* Get the parameter position, or null if named
297
* @return parameter position
298
*/
299
Integer getPosition();
300
301
/**
302
* Get the Java type of the parameter
303
* @return parameter type
304
*/
305
Class<T> getParameterType();
306
}
307
```
308
309
**Usage Example:**
310
311
```java
312
EntityManager em = emf.createEntityManager();
313
314
// Simple query
315
Query query = em.createQuery("SELECT u FROM User u WHERE u.name = :name");
316
query.setParameter("name", "Alice");
317
query.setMaxResults(10);
318
query.setFirstResult(0);
319
List users = query.getResultList();
320
321
// Get single result
322
Query singleQuery = em.createQuery("SELECT u FROM User u WHERE u.id = :id");
323
singleQuery.setParameter("id", 1L);
324
Object user = singleQuery.getSingleResult();
325
326
// Update query
327
Query updateQuery = em.createQuery("UPDATE User u SET u.status = :status WHERE u.active = false");
328
updateQuery.setParameter("status", "INACTIVE");
329
int updated = updateQuery.executeUpdate();
330
331
// Stream results
332
try (Stream<User> stream = em.createQuery("SELECT u FROM User u", User.class).getResultStream()) {
333
stream.forEach(u -> System.out.println(u.getName()));
334
}
335
336
// Query hints
337
query.setHint("jakarta.persistence.query.timeout", 5000);
338
query.setHint("jakarta.persistence.cache.retrieveMode", CacheRetrieveMode.BYPASS);
339
340
// Temporal parameters
341
Query dateQuery = em.createQuery("SELECT o FROM Order o WHERE o.orderDate > :date");
342
dateQuery.setParameter("date", new Date(), TemporalType.DATE);
343
```
344
345
### TypedQuery Interface
346
347
Execute type-safe queries with compile-time checking.
348
349
```java { .api }
350
/**
351
* Interface for executing typed queries
352
* @since 2.0
353
*/
354
public interface TypedQuery<X> extends Query {
355
/**
356
* Execute a SELECT query and return the query results as a typed List
357
* @return list of results
358
*/
359
List<X> getResultList();
360
361
/**
362
* Execute a SELECT query that returns a single typed result
363
* @return the result
364
* @throws NoResultException if no result
365
* @throws NonUniqueResultException if more than one result
366
*/
367
X getSingleResult();
368
369
/**
370
* Execute a SELECT query and return results as a typed Stream
371
* @return a stream of the results
372
* @since 2.2
373
*/
374
Stream<X> getResultStream();
375
376
/**
377
* Set the maximum number of results
378
* @param maxResult maximum number of results
379
* @return the same query instance
380
*/
381
TypedQuery<X> setMaxResults(int maxResult);
382
383
/**
384
* Set the position of the first result
385
* @param startPosition position of first result
386
* @return the same query instance
387
*/
388
TypedQuery<X> setFirstResult(int startPosition);
389
390
/**
391
* Set a query hint
392
* @param hintName hint name
393
* @param value hint value
394
* @return the same query instance
395
*/
396
TypedQuery<X> setHint(String hintName, Object value);
397
398
/**
399
* Bind a value to a named parameter
400
* @param name parameter name
401
* @param value parameter value
402
* @return the same query instance
403
*/
404
<T> TypedQuery<X> setParameter(String name, T value);
405
406
/**
407
* Bind a value to a positional parameter
408
* @param position parameter position
409
* @param value parameter value
410
* @return the same query instance
411
*/
412
TypedQuery<X> setParameter(int position, Object value);
413
414
/**
415
* Bind a Calendar value to a named parameter
416
* @param name parameter name
417
* @param value parameter value
418
* @param temporalType temporal type
419
* @return the same query instance
420
*/
421
TypedQuery<X> setParameter(String name, Calendar value, TemporalType temporalType);
422
423
/**
424
* Bind a Date value to a named parameter
425
* @param name parameter name
426
* @param value parameter value
427
* @param temporalType temporal type
428
* @return the same query instance
429
*/
430
TypedQuery<X> setParameter(String name, Date value, TemporalType temporalType);
431
432
/**
433
* Bind a Calendar value to a positional parameter
434
* @param position parameter position
435
* @param value parameter value
436
* @param temporalType temporal type
437
* @return the same query instance
438
*/
439
TypedQuery<X> setParameter(int position, Calendar value, TemporalType temporalType);
440
441
/**
442
* Bind a Date value to a positional parameter
443
* @param position parameter position
444
* @param value parameter value
445
* @param temporalType temporal type
446
* @return the same query instance
447
*/
448
TypedQuery<X> setParameter(int position, Date value, TemporalType temporalType);
449
450
/**
451
* Bind a Parameter object
452
* @param param parameter object
453
* @param value parameter value
454
* @return the same query instance
455
*/
456
<T> TypedQuery<X> setParameter(Parameter<T> param, T value);
457
458
/**
459
* Bind a Calendar Parameter
460
* @param param parameter object
461
* @param value parameter value
462
* @param temporalType temporal type
463
* @return the same query instance
464
*/
465
TypedQuery<X> setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType);
466
467
/**
468
* Bind a Date Parameter
469
* @param param parameter object
470
* @param value parameter value
471
* @param temporalType temporal type
472
* @return the same query instance
473
*/
474
TypedQuery<X> setParameter(Parameter<Date> param, Date value, TemporalType temporalType);
475
476
/**
477
* Set the flush mode
478
* @param flushMode flush mode
479
* @return the same query instance
480
*/
481
TypedQuery<X> setFlushMode(FlushModeType flushMode);
482
483
/**
484
* Set the lock mode
485
* @param lockMode lock mode
486
* @return the same query instance
487
*/
488
TypedQuery<X> setLockMode(LockModeType lockMode);
489
}
490
```
491
492
**Usage Example:**
493
494
```java
495
EntityManager em = emf.createEntityManager();
496
497
// Typed query
498
TypedQuery<User> query = em.createQuery(
499
"SELECT u FROM User u WHERE u.email LIKE :pattern", User.class);
500
query.setParameter("pattern", "%@example.com");
501
List<User> users = query.getResultList();
502
503
// Single typed result
504
TypedQuery<User> singleQuery = em.createQuery(
505
"SELECT u FROM User u WHERE u.username = :username", User.class);
506
singleQuery.setParameter("username", "admin");
507
User admin = singleQuery.getSingleResult();
508
509
// Typed stream
510
TypedQuery<Order> orderQuery = em.createQuery(
511
"SELECT o FROM Order o WHERE o.orderDate >= :date", Order.class);
512
orderQuery.setParameter("date", LocalDate.now().minusDays(7));
513
try (Stream<Order> orders = orderQuery.getResultStream()) {
514
orders.filter(o -> o.getTotal().compareTo(BigDecimal.valueOf(100)) > 0)
515
.forEach(System.out::println);
516
}
517
```
518
519
### StoredProcedureQuery Interface
520
521
Execute stored procedures.
522
523
```java { .api }
524
/**
525
* Interface for controlling stored procedure query execution
526
* @since 2.1
527
*/
528
public interface StoredProcedureQuery extends Query {
529
/**
530
* Register a stored procedure parameter
531
* @param position parameter position (numbered from 1)
532
* @param type parameter type
533
* @param mode parameter mode
534
* @return the same query instance
535
*/
536
StoredProcedureQuery registerStoredProcedureParameter(int position, Class type, ParameterMode mode);
537
538
/**
539
* Register a named stored procedure parameter
540
* @param parameterName parameter name
541
* @param type parameter type
542
* @param mode parameter mode
543
* @return the same query instance
544
*/
545
StoredProcedureQuery registerStoredProcedureParameter(String parameterName, Class type, ParameterMode mode);
546
547
/**
548
* Set a hint for the query
549
* @param hintName hint name
550
* @param value hint value
551
* @return the same query instance
552
*/
553
StoredProcedureQuery setHint(String hintName, Object value);
554
555
/**
556
* Bind a value to a named parameter
557
* @param name parameter name
558
* @param value parameter value
559
* @return the same query instance
560
*/
561
<T> StoredProcedureQuery setParameter(String name, T value);
562
563
/**
564
* Bind a value to a positional parameter
565
* @param position parameter position
566
* @param value parameter value
567
* @return the same query instance
568
*/
569
StoredProcedureQuery setParameter(int position, Object value);
570
571
/**
572
* Bind a Calendar value to a named parameter
573
* @param name parameter name
574
* @param value parameter value
575
* @param temporalType temporal type
576
* @return the same query instance
577
*/
578
StoredProcedureQuery setParameter(String name, Calendar value, TemporalType temporalType);
579
580
/**
581
* Bind a Date value to a named parameter
582
* @param name parameter name
583
* @param value parameter value
584
* @param temporalType temporal type
585
* @return the same query instance
586
*/
587
StoredProcedureQuery setParameter(String name, Date value, TemporalType temporalType);
588
589
/**
590
* Bind a Calendar value to a positional parameter
591
* @param position parameter position
592
* @param value parameter value
593
* @param temporalType temporal type
594
* @return the same query instance
595
*/
596
StoredProcedureQuery setParameter(int position, Calendar value, TemporalType temporalType);
597
598
/**
599
* Bind a Date value to a positional parameter
600
* @param position parameter position
601
* @param value parameter value
602
* @param temporalType temporal type
603
* @return the same query instance
604
*/
605
StoredProcedureQuery setParameter(int position, Date value, TemporalType temporalType);
606
607
/**
608
* Bind a Parameter object
609
* @param param parameter object
610
* @param value parameter value
611
* @return the same query instance
612
*/
613
<T> StoredProcedureQuery setParameter(Parameter<T> param, T value);
614
615
/**
616
* Bind a Calendar Parameter
617
* @param param parameter object
618
* @param value parameter value
619
* @param temporalType temporal type
620
* @return the same query instance
621
*/
622
StoredProcedureQuery setParameter(Parameter<Calendar> param, Calendar value, TemporalType temporalType);
623
624
/**
625
* Bind a Date Parameter
626
* @param param parameter object
627
* @param value parameter value
628
* @param temporalType temporal type
629
* @return the same query instance
630
*/
631
StoredProcedureQuery setParameter(Parameter<Date> param, Date value, TemporalType temporalType);
632
633
/**
634
* Set the flush mode
635
* @param flushMode flush mode
636
* @return the same query instance
637
*/
638
StoredProcedureQuery setFlushMode(FlushModeType flushMode);
639
640
/**
641
* Execute the stored procedure
642
* @return true if the first result is a result set
643
*/
644
boolean execute();
645
646
/**
647
* Get the update count or -1 if not applicable
648
* @return update count
649
*/
650
int getUpdateCount();
651
652
/**
653
* Check if there are more results available
654
* @return true if more results are available
655
*/
656
boolean hasMoreResults();
657
658
/**
659
* Get the output parameter value by position
660
* @param position parameter position
661
* @return output parameter value
662
*/
663
Object getOutputParameterValue(int position);
664
665
/**
666
* Get the output parameter value by name
667
* @param parameterName parameter name
668
* @return output parameter value
669
*/
670
Object getOutputParameterValue(String parameterName);
671
}
672
```
673
674
**Usage Example:**
675
676
```java
677
EntityManager em = emf.createEntityManager();
678
679
// Create stored procedure query
680
StoredProcedureQuery query = em.createStoredProcedureQuery("calculate_bonus");
681
682
// Register parameters
683
query.registerStoredProcedureParameter(1, Long.class, ParameterMode.IN);
684
query.registerStoredProcedureParameter(2, BigDecimal.class, ParameterMode.OUT);
685
query.registerStoredProcedureParameter("result", String.class, ParameterMode.OUT);
686
687
// Set input parameters
688
query.setParameter(1, 12345L);
689
690
// Execute
691
query.execute();
692
693
// Get output parameters
694
BigDecimal bonus = (BigDecimal) query.getOutputParameterValue(2);
695
String result = (String) query.getOutputParameterValue("result");
696
697
// With result sets
698
StoredProcedureQuery spQuery = em.createStoredProcedureQuery("get_employees", Employee.class);
699
boolean hasResults = spQuery.execute();
700
if (hasResults) {
701
List<Employee> employees = spQuery.getResultList();
702
}
703
```
704
705
### Named Queries
706
707
Define static, reusable queries.
708
709
```java { .api }
710
/**
711
* Specifies a named JPQL query
712
* @since 1.0
713
*/
714
@Target({TYPE})
715
@Retention(RUNTIME)
716
@Repeatable(NamedQueries.class)
717
public @interface NamedQuery {
718
/** (Required) The name of the query */
719
String name();
720
721
/** (Required) The JPQL query string */
722
String query();
723
724
/** (Optional) The lock mode type */
725
LockModeType lockMode() default LockModeType.NONE;
726
727
/** (Optional) Query hints */
728
QueryHint[] hints() default {};
729
}
730
731
/**
732
* Groups NamedQuery annotations
733
* @since 1.0
734
*/
735
@Target({TYPE})
736
@Retention(RUNTIME)
737
public @interface NamedQueries {
738
/** Array of named queries */
739
NamedQuery[] value();
740
}
741
742
/**
743
* Specifies a named native SQL query
744
* @since 1.0
745
*/
746
@Target({TYPE})
747
@Retention(RUNTIME)
748
@Repeatable(NamedNativeQueries.class)
749
public @interface NamedNativeQuery {
750
/** (Required) The name of the query */
751
String name();
752
753
/** (Required) The SQL query string */
754
String query();
755
756
/** (Optional) Query hints */
757
QueryHint[] hints() default {};
758
759
/** (Optional) The class of the result */
760
Class resultClass() default void.class;
761
762
/** (Optional) The name of the SQL result set mapping */
763
String resultSetMapping() default "";
764
}
765
766
/**
767
* Groups NamedNativeQuery annotations
768
* @since 1.0
769
*/
770
@Target({TYPE})
771
@Retention(RUNTIME)
772
public @interface NamedNativeQueries {
773
/** Array of named native queries */
774
NamedNativeQuery[] value();
775
}
776
777
/**
778
* Specifies a query hint
779
* @since 1.0
780
*/
781
@Target({})
782
@Retention(RUNTIME)
783
public @interface QueryHint {
784
/** (Required) The name of the hint */
785
String name();
786
787
/** (Required) The value of the hint */
788
String value();
789
}
790
791
/**
792
* Specifies a named stored procedure query
793
* @since 2.1
794
*/
795
@Target({TYPE})
796
@Retention(RUNTIME)
797
@Repeatable(NamedStoredProcedureQueries.class)
798
public @interface NamedStoredProcedureQuery {
799
/** (Required) The name of the query */
800
String name();
801
802
/** (Required) The name of the stored procedure */
803
String procedureName();
804
805
/** (Optional) Information about stored procedure parameters */
806
StoredProcedureParameter[] parameters() default {};
807
808
/** (Optional) The class of the result */
809
Class[] resultClasses() default {};
810
811
/** (Optional) The names of SQL result set mappings */
812
String[] resultSetMappings() default {};
813
814
/** (Optional) Query hints */
815
QueryHint[] hints() default {};
816
}
817
818
/**
819
* Groups NamedStoredProcedureQuery annotations
820
* @since 2.1
821
*/
822
@Target({TYPE})
823
@Retention(RUNTIME)
824
public @interface NamedStoredProcedureQueries {
825
/** Array of named stored procedure queries */
826
NamedStoredProcedureQuery[] value();
827
}
828
829
/**
830
* Specifies a parameter of a named stored procedure query
831
* @since 2.1
832
*/
833
@Target({})
834
@Retention(RUNTIME)
835
public @interface StoredProcedureParameter {
836
/** (Optional) The name of the parameter */
837
String name() default "";
838
839
/** (Optional) The parameter mode */
840
ParameterMode mode() default ParameterMode.IN;
841
842
/** (Required) The type of the parameter */
843
Class type();
844
}
845
```
846
847
**Usage Example:**
848
849
```java
850
@Entity
851
@NamedQueries({
852
@NamedQuery(
853
name = "User.findAll",
854
query = "SELECT u FROM User u ORDER BY u.name"
855
),
856
@NamedQuery(
857
name = "User.findByEmail",
858
query = "SELECT u FROM User u WHERE u.email = :email",
859
hints = {
860
@QueryHint(name = "jakarta.persistence.cache.retrieveMode", value = "USE")
861
}
862
),
863
@NamedQuery(
864
name = "User.findActiveWithOrders",
865
query = "SELECT DISTINCT u FROM User u LEFT JOIN FETCH u.orders WHERE u.active = true"
866
)
867
})
868
@NamedNativeQueries({
869
@NamedNativeQuery(
870
name = "User.findByNativeSQL",
871
query = "SELECT * FROM users WHERE name LIKE ?",
872
resultClass = User.class
873
)
874
})
875
@NamedStoredProcedureQueries({
876
@NamedStoredProcedureQuery(
877
name = "User.calculateDiscount",
878
procedureName = "sp_calculate_user_discount",
879
parameters = {
880
@StoredProcedureParameter(name = "userId", type = Long.class, mode = ParameterMode.IN),
881
@StoredProcedureParameter(name = "discount", type = BigDecimal.class, mode = ParameterMode.OUT)
882
}
883
)
884
})
885
public class User {
886
@Id
887
private Long id;
888
private String name;
889
private String email;
890
private boolean active;
891
892
@OneToMany(mappedBy = "user")
893
private List<Order> orders;
894
}
895
896
// Using named queries
897
TypedQuery<User> query = em.createNamedQuery("User.findByEmail", User.class);
898
query.setParameter("email", "alice@example.com");
899
User user = query.getSingleResult();
900
901
Query nativeQuery = em.createNamedQuery("User.findByNativeSQL");
902
nativeQuery.setParameter(1, "A%");
903
List<User> users = nativeQuery.getResultList();
904
905
StoredProcedureQuery spQuery = em.createNamedStoredProcedureQuery("User.calculateDiscount");
906
spQuery.setParameter("userId", 1L);
907
spQuery.execute();
908
BigDecimal discount = (BigDecimal) spQuery.getOutputParameterValue("discount");
909
```
910
911
### SQL Result Set Mapping
912
913
Map native SQL query results to entities or custom result types.
914
915
```java { .api }
916
/**
917
* Specifies the mapping of the result of a native SQL query or stored procedure
918
* @since 1.0
919
*/
920
@Target({TYPE})
921
@Retention(RUNTIME)
922
@Repeatable(SqlResultSetMappings.class)
923
public @interface SqlResultSetMapping {
924
/** (Required) The name of the result set mapping */
925
String name();
926
927
/** (Optional) Entities to map to */
928
EntityResult[] entities() default {};
929
930
/** (Optional) Constructor results */
931
ConstructorResult[] classes() default {};
932
933
/** (Optional) Column results */
934
ColumnResult[] columns() default {};
935
}
936
937
/**
938
* Groups SqlResultSetMapping annotations
939
* @since 1.0
940
*/
941
@Target({TYPE})
942
@Retention(RUNTIME)
943
public @interface SqlResultSetMappings {
944
/** Array of result set mappings */
945
SqlResultSetMapping[] value();
946
}
947
948
/**
949
* Used to map a SQL result to an entity
950
* @since 1.0
951
*/
952
@Target({})
953
@Retention(RUNTIME)
954
public @interface EntityResult {
955
/** (Required) The class of the entity */
956
Class entityClass();
957
958
/** (Optional) Field mappings */
959
FieldResult[] fields() default {};
960
961
/** (Optional) The name of the discriminator column */
962
String discriminatorColumn() default "";
963
}
964
965
/**
966
* Used to map columns to entity fields
967
* @since 1.0
968
*/
969
@Target({})
970
@Retention(RUNTIME)
971
public @interface FieldResult {
972
/** (Required) Name of the persistent field or property */
973
String name();
974
975
/** (Required) Name of the column in the SELECT list */
976
String column();
977
}
978
979
/**
980
* Used to map SQL query results to a constructor
981
* @since 2.1
982
*/
983
@Target({})
984
@Retention(RUNTIME)
985
public @interface ConstructorResult {
986
/** (Required) The class whose constructor is to be invoked */
987
Class targetClass();
988
989
/** (Required) The columns to be passed to the constructor */
990
ColumnResult[] columns();
991
}
992
993
/**
994
* Used to map a column in the SELECT list to a constructor parameter or scalar result
995
* @since 1.0
996
*/
997
@Target({})
998
@Retention(RUNTIME)
999
public @interface ColumnResult {
1000
/** (Required) The name of the column in the SELECT list */
1001
String name();
1002
1003
/** (Optional) The Java type of the column */
1004
Class type() default void.class;
1005
}
1006
```
1007
1008
**Usage Example:**
1009
1010
```java
1011
@Entity
1012
@SqlResultSetMappings({
1013
@SqlResultSetMapping(
1014
name = "UserOrderMapping",
1015
entities = {
1016
@EntityResult(
1017
entityClass = User.class,
1018
fields = {
1019
@FieldResult(name = "id", column = "user_id"),
1020
@FieldResult(name = "name", column = "user_name")
1021
}
1022
),
1023
@EntityResult(
1024
entityClass = Order.class,
1025
fields = {
1026
@FieldResult(name = "id", column = "order_id"),
1027
@FieldResult(name = "orderDate", column = "order_date")
1028
}
1029
)
1030
}
1031
),
1032
@SqlResultSetMapping(
1033
name = "UserSummaryMapping",
1034
classes = {
1035
@ConstructorResult(
1036
targetClass = UserSummary.class,
1037
columns = {
1038
@ColumnResult(name = "user_id", type = Long.class),
1039
@ColumnResult(name = "user_name", type = String.class),
1040
@ColumnResult(name = "order_count", type = Long.class)
1041
}
1042
)
1043
}
1044
),
1045
@SqlResultSetMapping(
1046
name = "ScalarMapping",
1047
columns = {
1048
@ColumnResult(name = "total", type = BigDecimal.class),
1049
@ColumnResult(name = "count", type = Long.class)
1050
}
1051
)
1052
})
1053
public class User {
1054
@Id
1055
private Long id;
1056
private String name;
1057
}
1058
1059
// Using result set mapping
1060
Query query = em.createNativeQuery(
1061
"SELECT u.id as user_id, u.name as user_name, o.id as order_id, o.order_date " +
1062
"FROM users u JOIN orders o ON u.id = o.user_id",
1063
"UserOrderMapping"
1064
);
1065
List results = query.getResultList();
1066
1067
// Constructor result mapping
1068
Query summaryQuery = em.createNativeQuery(
1069
"SELECT u.id as user_id, u.name as user_name, COUNT(o.id) as order_count " +
1070
"FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id, u.name",
1071
"UserSummaryMapping"
1072
);
1073
List<UserSummary> summaries = summaryQuery.getResultList();
1074
1075
// Scalar result mapping
1076
Query scalarQuery = em.createNativeQuery(
1077
"SELECT SUM(amount) as total, COUNT(*) as count FROM orders",
1078
"ScalarMapping"
1079
);
1080
Object[] result = (Object[]) scalarQuery.getSingleResult();
1081
BigDecimal total = (BigDecimal) result[0];
1082
Long count = (Long) result[1];
1083
```
1084
1085
### Tuple Results
1086
1087
Work with multi-column query results.
1088
1089
```java { .api }
1090
/**
1091
* Interface for extracting values from Tuple results
1092
* @since 2.0
1093
*/
1094
public interface Tuple {
1095
/**
1096
* Get the value of the specified element
1097
* @param tupleElement tuple element
1098
* @return value
1099
*/
1100
<X> X get(TupleElement<X> tupleElement);
1101
1102
/**
1103
* Get the value at the specified position
1104
* @param i position (numbered from 0)
1105
* @param type the type of the result
1106
* @return value
1107
*/
1108
<X> X get(int i, Class<X> type);
1109
1110
/**
1111
* Get the value at the specified position
1112
* @param i position (numbered from 0)
1113
* @return value
1114
*/
1115
Object get(int i);
1116
1117
/**
1118
* Get the value by alias
1119
* @param alias alias name
1120
* @param type the type of the result
1121
* @return value
1122
*/
1123
<X> X get(String alias, Class<X> type);
1124
1125
/**
1126
* Get the value by alias
1127
* @param alias alias name
1128
* @return value
1129
*/
1130
Object get(String alias);
1131
1132
/**
1133
* Return the values of the tuple as an array
1134
* @return array of values
1135
*/
1136
Object[] toArray();
1137
1138
/**
1139
* Return the tuple elements
1140
* @return tuple elements
1141
*/
1142
List<TupleElement<?>> getElements();
1143
}
1144
1145
/**
1146
* Represents a tuple element
1147
* @since 2.0
1148
*/
1149
public interface TupleElement<X> {
1150
/**
1151
* Return the Java type of the element
1152
* @return Java type
1153
*/
1154
Class<? extends X> getJavaType();
1155
1156
/**
1157
* Return the alias of the element
1158
* @return alias
1159
*/
1160
String getAlias();
1161
}
1162
```
1163
1164
**Usage Example:**
1165
1166
```java
1167
EntityManager em = emf.createEntityManager();
1168
1169
// Tuple query
1170
CriteriaBuilder cb = em.getCriteriaBuilder();
1171
CriteriaQuery<Tuple> cq = cb.createTupleQuery();
1172
Root<User> user = cq.from(User.class);
1173
cq.multiselect(
1174
user.get("id").alias("userId"),
1175
user.get("name").alias("userName"),
1176
cb.count(user.get("orders")).alias("orderCount")
1177
);
1178
cq.groupBy(user.get("id"), user.get("name"));
1179
1180
TypedQuery<Tuple> query = em.createQuery(cq);
1181
List<Tuple> results = query.getResultList();
1182
1183
for (Tuple tuple : results) {
1184
Long id = tuple.get("userId", Long.class);
1185
String name = tuple.get("userName", String.class);
1186
Long count = tuple.get("orderCount", Long.class);
1187
System.out.println(name + " has " + count + " orders");
1188
}
1189
```
1190