0
# Entity Mapping
1
2
Hibernate Core provides extensive annotations and mapping capabilities beyond the standard JPA annotations. These include advanced caching, fetching strategies, custom types, natural identifiers, and specialized entity behaviors.
3
4
## Capabilities
5
6
### Caching Annotations
7
8
Advanced second-level caching configuration for entities and collections.
9
10
```java { .api }
11
/**
12
* Configures second-level caching for an entity or collection
13
*/
14
@Target({TYPE, METHOD, FIELD})
15
@Retention(RUNTIME)
16
public @interface Cache {
17
/**
18
* Cache concurrency strategy
19
* @return the concurrency strategy
20
*/
21
CacheConcurrencyStrategy usage();
22
23
/**
24
* Cache region name
25
* @return the region name (defaults to entity/collection name)
26
*/
27
String region() default "";
28
29
/**
30
* Include lazy attributes in cache when loaded
31
* @return whether to cache lazy fields (default true)
32
*/
33
boolean includeLazy() default true;
34
}
35
36
/**
37
* Cache concurrency strategies
38
*/
39
public enum CacheConcurrencyStrategy {
40
/** No concurrency strategy specified */
41
NONE,
42
/** Read-only access - immutable objects */
43
READ_ONLY,
44
/** Read/write access with no locking - for rarely updated data */
45
NONSTRICT_READ_WRITE,
46
/** Read/write access with soft locks - for commonly updated data */
47
READ_WRITE,
48
/** Transactional access - requires JTA/XA integration */
49
TRANSACTIONAL
50
}
51
```
52
53
### Cache Runtime Interface
54
55
Runtime interface for programmatic cache interaction and management.
56
57
```java { .api }
58
/**
59
* Runtime cache interface for programmatic cache operations
60
*/
61
public interface Cache {
62
/**
63
* Get an item from the cache
64
* @param key the cache key
65
* @return the cached item or null if not found
66
*/
67
Object get(Object key);
68
69
/**
70
* Put an item in the cache
71
* @param key the cache key
72
* @param value the value to cache
73
*/
74
void put(Object key, Object value);
75
76
/**
77
* Remove an item from the cache
78
* @param key the cache key
79
*/
80
void evict(Object key);
81
82
/**
83
* Clear all entries from the cache
84
*/
85
void clear();
86
87
/**
88
* Destroy/close the cache
89
*/
90
void destroy();
91
92
/**
93
* Get the cache region name
94
* @return the region name
95
*/
96
String getRegionName();
97
98
/**
99
* Check if the cache contains the specified key
100
* @param key the cache key
101
* @return true if key exists in cache
102
*/
103
boolean contains(Object key);
104
105
/**
106
* Get cache statistics
107
* @return CacheStatistics instance or null if statistics disabled
108
*/
109
CacheStatistics getStatistics();
110
}
111
112
/**
113
* Cache statistics interface
114
*/
115
public interface CacheStatistics {
116
/**
117
* Get the number of cache hits
118
* @return hit count
119
*/
120
long getHitCount();
121
122
/**
123
* Get the number of cache misses
124
* @return miss count
125
*/
126
long getMissCount();
127
128
/**
129
* Get the cache hit ratio
130
* @return hit ratio (0.0 to 1.0)
131
*/
132
double getHitRatio();
133
134
/**
135
* Get the number of cached elements
136
* @return element count
137
*/
138
long getElementCountInMemory();
139
140
/**
141
* Clear the statistics
142
*/
143
void clear();
144
}
145
```
146
147
### Fetching Strategy Annotations
148
149
Control how associations are fetched from the database.
150
151
```java { .api }
152
/**
153
* Specifies the fetch strategy for an association
154
*/
155
@Target({METHOD, FIELD})
156
@Retention(RUNTIME)
157
public @interface Fetch {
158
/**
159
* The fetch mode to use
160
* @return the fetch mode
161
*/
162
FetchMode value();
163
}
164
165
/**
166
* Available fetch modes
167
*/
168
public enum FetchMode {
169
/** Use a select statement to load the association */
170
SELECT,
171
/** Use an outer join to load the association */
172
JOIN,
173
/** Use a subquery to load the association */
174
SUBSELECT
175
}
176
177
/**
178
* Batch size for fetching associations or entities
179
*/
180
@Target({TYPE, METHOD, FIELD})
181
@Retention(RUNTIME)
182
public @interface BatchSize {
183
/**
184
* The batch size
185
* @return the batch size (must be positive)
186
*/
187
int size();
188
}
189
190
/**
191
* Lazy loading group for fine-grained lazy loading
192
*/
193
@Target({METHOD, FIELD})
194
@Retention(RUNTIME)
195
public @interface LazyGroup {
196
/**
197
* The lazy group name
198
* @return the group name
199
*/
200
String value();
201
}
202
```
203
204
### Natural Identifier Annotations
205
206
Support for natural identifiers as alternatives to surrogate keys.
207
208
```java { .api }
209
/**
210
* Marks a property as part of the natural identifier
211
*/
212
@Target({METHOD, FIELD})
213
@Retention(RUNTIME)
214
public @interface NaturalId {
215
/**
216
* Whether the natural ID is mutable
217
* @return true if mutable
218
*/
219
boolean mutable() default false;
220
}
221
222
/**
223
* Cache configuration specifically for natural ID lookups
224
*/
225
@Target(TYPE)
226
@Retention(RUNTIME)
227
public @interface NaturalIdCache {
228
/**
229
* Cache region for natural ID lookups
230
* @return the cache region name
231
*/
232
String region() default "";
233
}
234
```
235
236
### Custom Type Annotations
237
238
Specify custom types for properties and parameters.
239
240
```java { .api }
241
/**
242
* Specifies a custom Hibernate type for a property
243
*/
244
@Target({METHOD, FIELD})
245
@Retention(RUNTIME)
246
public @interface Type {
247
/**
248
* The type implementation class
249
* @return the type class
250
*/
251
Class<? extends UserType<?>> value() default void.class;
252
253
/**
254
* Parameters for the type
255
* @return array of parameters
256
*/
257
Parameter[] parameters() default {};
258
}
259
260
/**
261
* Specify Java type for a property
262
*/
263
@Target({METHOD, FIELD, PARAMETER})
264
@Retention(RUNTIME)
265
public @interface JavaType {
266
/**
267
* The Java type descriptor class
268
* @return the descriptor class
269
*/
270
Class<? extends JavaTypeDescriptor<?>> value();
271
}
272
273
/**
274
* Specify JDBC type for a property
275
*/
276
@Target({METHOD, FIELD})
277
@Retention(RUNTIME)
278
public @interface JdbcType {
279
/**
280
* The JDBC type descriptor class
281
* @return the descriptor class
282
*/
283
Class<? extends JdbcType> value();
284
}
285
```
286
287
### Entity Behavior Annotations
288
289
Control entity lifecycle and behavior.
290
291
```java { .api }
292
/**
293
* Entity is immutable (read-only)
294
*/
295
@Target(TYPE)
296
@Retention(RUNTIME)
297
public @interface Immutable {
298
}
299
300
/**
301
* Generate SQL dynamically for inserts
302
*/
303
@Target(TYPE)
304
@Retention(RUNTIME)
305
public @interface DynamicInsert {
306
/**
307
* Whether to use dynamic inserts
308
* @return true for dynamic inserts
309
*/
310
boolean value() default true;
311
}
312
313
/**
314
* Generate SQL dynamically for updates
315
*/
316
@Target(TYPE)
317
@Retention(RUNTIME)
318
public @interface DynamicUpdate {
319
/**
320
* Whether to use dynamic updates
321
* @return true for dynamic updates
322
*/
323
boolean value() default true;
324
}
325
326
/**
327
* Select before update optimization
328
*/
329
@Target(TYPE)
330
@Retention(RUNTIME)
331
public @interface SelectBeforeUpdate {
332
/**
333
* Whether to select before update
334
* @return true to select before update
335
*/
336
boolean value() default true;
337
}
338
339
/**
340
* Optimistic locking strategy
341
*/
342
@Target(TYPE)
343
@Retention(RUNTIME)
344
public @interface OptimisticLocking {
345
/**
346
* The optimistic locking type
347
* @return the locking type
348
*/
349
OptimisticLockType type() default OptimisticLockType.VERSION;
350
}
351
352
/**
353
* Optimistic locking types
354
*/
355
public enum OptimisticLockType {
356
/** No optimistic locking */
357
NONE,
358
/** Version-based locking */
359
VERSION,
360
/** Dirty fields locking */
361
DIRTY,
362
/** All fields locking */
363
ALL
364
}
365
```
366
367
### Timestamp and Generated Value Annotations
368
369
Automatic timestamp and value generation.
370
371
```java { .api }
372
/**
373
* Automatically set creation timestamp
374
*/
375
@Target({METHOD, FIELD})
376
@Retention(RUNTIME)
377
public @interface CreationTimestamp {
378
}
379
380
/**
381
* Automatically set update timestamp
382
*/
383
@Target({METHOD, FIELD})
384
@Retention(RUNTIME)
385
public @interface UpdateTimestamp {
386
}
387
388
/**
389
* Specify generation strategy for properties
390
*/
391
@Target({METHOD, FIELD})
392
@Retention(RUNTIME)
393
public @interface Generated {
394
/**
395
* When the value is generated
396
* @return the generation timing
397
*/
398
GenerationTime value();
399
}
400
401
/**
402
* Generation timing options
403
*/
404
public enum GenerationTime {
405
/** Never generated */
406
NEVER,
407
/** Generated on insert only */
408
INSERT,
409
/** Generated on insert and update */
410
ALWAYS
411
}
412
```
413
414
### Formula and Computed Properties
415
416
Define computed properties and SQL formulas.
417
418
```java { .api }
419
/**
420
* SQL formula for computed properties
421
*/
422
@Target({METHOD, FIELD})
423
@Retention(RUNTIME)
424
public @interface Formula {
425
/**
426
* The SQL formula
427
* @return the SQL expression
428
*/
429
String value();
430
}
431
432
/**
433
* Derived property based on other properties
434
*/
435
@Target({METHOD, FIELD})
436
@Retention(RUNTIME)
437
public @interface ColumnTransformer {
438
/**
439
* SQL expression for reading the column
440
* @return the read expression
441
*/
442
String read() default "";
443
444
/**
445
* SQL expression for writing the column
446
* @return the write expression
447
*/
448
String write() default "";
449
}
450
```
451
452
### Collection and Association Annotations
453
454
Advanced collection and association mapping.
455
456
```java { .api }
457
/**
458
* Order collection by SQL expression
459
*/
460
@Target({METHOD, FIELD})
461
@Retention(RUNTIME)
462
public @interface OrderBy {
463
/**
464
* SQL ORDER BY clause
465
* @return the ordering clause
466
*/
467
String clause();
468
}
469
470
/**
471
* Sort collection in memory
472
*/
473
@Target({METHOD, FIELD})
474
@Retention(RUNTIME)
475
public @interface Sort {
476
/**
477
* The sorting type
478
* @return the sort type
479
*/
480
SortType type() default SortType.UNSORTED;
481
482
/**
483
* Comparator class for custom sorting
484
* @return the comparator class
485
*/
486
Class<? extends Comparator> comparator() default void.class;
487
}
488
489
/**
490
* How to handle missing referenced entities
491
*/
492
@Target({METHOD, FIELD})
493
@Retention(RUNTIME)
494
public @interface NotFound {
495
/**
496
* The action to take for missing references
497
* @return the not found action
498
*/
499
NotFoundAction action() default NotFoundAction.EXCEPTION;
500
}
501
502
/**
503
* Actions for missing references
504
*/
505
public enum NotFoundAction {
506
/** Throw exception */
507
EXCEPTION,
508
/** Ignore missing reference */
509
IGNORE
510
}
511
512
/**
513
* Database cascade actions
514
*/
515
@Target({METHOD, FIELD})
516
@Retention(RUNTIME)
517
public @interface OnDelete {
518
/**
519
* The cascade action
520
* @return the delete action
521
*/
522
OnDeleteAction action();
523
}
524
525
/**
526
* Database cascade actions
527
*/
528
public enum OnDeleteAction {
529
/** No action */
530
NO_ACTION,
531
/** Cascade delete */
532
CASCADE,
533
/** Set to null */
534
SET_NULL,
535
/** Set to default */
536
SET_DEFAULT,
537
/** Restrict delete */
538
RESTRICT
539
}
540
```
541
542
### Query and Filter Annotations
543
544
Named queries and entity filtering.
545
546
```java { .api }
547
/**
548
* Named HQL/JPQL query
549
*/
550
@Target(TYPE)
551
@Retention(RUNTIME)
552
@Repeatable(NamedQueries.class)
553
public @interface NamedQuery {
554
/**
555
* Query name
556
* @return the query name
557
*/
558
String name();
559
560
/**
561
* HQL/JPQL query string
562
* @return the query string
563
*/
564
String query();
565
566
/**
567
* Query hints
568
* @return array of query hints
569
*/
570
QueryHint[] hints() default {};
571
}
572
573
/**
574
* Named native SQL query
575
*/
576
@Target(TYPE)
577
@Retention(RUNTIME)
578
@Repeatable(NamedNativeQueries.class)
579
public @interface NamedNativeQuery {
580
/**
581
* Query name
582
* @return the query name
583
*/
584
String name();
585
586
/**
587
* Native SQL query string
588
* @return the SQL string
589
*/
590
String query();
591
592
/**
593
* Result class
594
* @return the result class
595
*/
596
Class resultClass() default void.class;
597
598
/**
599
* Result set mapping name
600
* @return the mapping name
601
*/
602
String resultSetMapping() default "";
603
}
604
605
/**
606
* Define a filter for the entity
607
*/
608
@Target(TYPE)
609
@Retention(RUNTIME)
610
@Repeatable(Filters.class)
611
public @interface Filter {
612
/**
613
* Filter name
614
* @return the filter name
615
*/
616
String name();
617
618
/**
619
* Filter condition
620
* @return the SQL condition
621
*/
622
String condition() default "";
623
}
624
625
/**
626
* Filter definition with parameters
627
*/
628
@Target(TYPE)
629
@Retention(RUNTIME)
630
@Repeatable(FilterDefs.class)
631
public @interface FilterDef {
632
/**
633
* Filter name
634
* @return the filter name
635
*/
636
String name();
637
638
/**
639
* Filter parameters
640
* @return array of parameters
641
*/
642
ParamDef[] parameters() default {};
643
644
/**
645
* Default condition
646
* @return the default condition
647
*/
648
String defaultCondition() default "";
649
}
650
```
651
652
## Usage Examples
653
654
### Entity with Caching and Natural ID
655
656
```java
657
@Entity
658
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "users")
659
@NaturalIdCache
660
@DynamicUpdate
661
@SelectBeforeUpdate
662
public class User {
663
@Id
664
@GeneratedValue(strategy = GenerationType.IDENTITY)
665
private Long id;
666
667
@NaturalId(mutable = false)
668
@Column(unique = true, nullable = false)
669
private String username;
670
671
@Column(nullable = false)
672
private String name;
673
674
@CreationTimestamp
675
@Column(name = "created_date")
676
private LocalDateTime createdDate;
677
678
@UpdateTimestamp
679
@Column(name = "last_modified")
680
private LocalDateTime lastModified;
681
682
// Computed property
683
@Formula("(SELECT COUNT(*) FROM orders o WHERE o.customer_id = id)")
684
private int orderCount;
685
686
// Constructors, getters, setters
687
}
688
```
689
690
### Advanced Association Mapping
691
692
```java
693
@Entity
694
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
695
@FilterDef(name = "activeOrders", parameters = @ParamDef(name = "status", type = String.class))
696
public class Customer {
697
@Id
698
private Long id;
699
700
private String name;
701
702
@OneToMany(mappedBy = "customer", fetch = FetchType.LAZY, cascade = CascadeType.ALL)
703
@Fetch(FetchMode.SUBSELECT)
704
@BatchSize(size = 10)
705
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
706
@OrderBy("orderDate DESC")
707
@Filter(name = "activeOrders", condition = "status = :status")
708
private Set<Order> orders = new HashSet<>();
709
710
@ManyToOne(fetch = FetchType.LAZY)
711
@JoinColumn(name = "address_id")
712
@NotFound(action = NotFoundAction.IGNORE)
713
@OnDelete(action = OnDeleteAction.SET_NULL)
714
private Address primaryAddress;
715
716
// Constructors, getters, setters
717
}
718
```
719
720
### Custom Type Usage
721
722
```java
723
@Entity
724
public class Product {
725
@Id
726
private Long id;
727
728
private String name;
729
730
// Custom type for monetary values
731
@Type(value = MoneyType.class)
732
@Column(name = "price")
733
private Money price;
734
735
// JSON type mapping
736
@Type(value = JsonType.class)
737
@Column(name = "attributes", columnDefinition = "json")
738
private Map<String, Object> attributes;
739
740
// Custom Java type
741
@JavaType(UUIDJavaType.class)
742
@Column(name = "external_id")
743
private UUID externalId;
744
745
// Encrypted field
746
@ColumnTransformer(
747
read = "AES_DECRYPT(credit_card, 'key')",
748
write = "AES_ENCRYPT(?, 'key')"
749
)
750
@Column(name = "credit_card")
751
private String creditCard;
752
753
// Constructors, getters, setters
754
}
755
```
756
757
### Immutable Entity with Formula
758
759
```java
760
@Entity
761
@Immutable
762
@Table(name = "order_summary_view")
763
public class OrderSummary {
764
@Id
765
private Long orderId;
766
767
private String customerName;
768
769
@Formula("(SELECT SUM(oi.quantity * oi.price) FROM order_items oi WHERE oi.order_id = order_id)")
770
private BigDecimal totalAmount;
771
772
@Formula("(SELECT COUNT(*) FROM order_items oi WHERE oi.order_id = order_id)")
773
private Integer itemCount;
774
775
@Type(value = PostgreSQLEnumType.class)
776
@Column(name = "status", columnDefinition = "order_status")
777
private OrderStatus status;
778
779
// Constructors, getters, setters (no setters for immutable entity)
780
}
781
```
782
783
### Using Filters
784
785
```java
786
// Enable filter for active records only
787
@Entity
788
@FilterDef(name = "activeOnly", defaultCondition = "active = true")
789
@Filter(name = "activeOnly")
790
public class Employee {
791
@Id
792
private Long id;
793
794
private String name;
795
796
private boolean active;
797
798
// Entity definition
799
}
800
801
// Usage in session
802
session.enableFilter("activeOnly");
803
List<Employee> activeEmployees = session.createQuery("FROM Employee", Employee.class)
804
.getResultList(); // Only returns active employees
805
806
// Filter with parameters
807
session.enableFilter("activeOrders")
808
.setParameter("status", "ACTIVE");
809
```
810
811
### Lazy Loading Groups
812
813
```java
814
@Entity
815
public class Document {
816
@Id
817
private Long id;
818
819
private String title;
820
821
// Metadata loaded eagerly
822
private String author;
823
private LocalDateTime createdDate;
824
825
// Content loaded lazily in separate group
826
@Basic(fetch = FetchType.LAZY)
827
@LazyGroup("content")
828
@Lob
829
private String content;
830
831
// Binary data loaded lazily in separate group
832
@Basic(fetch = FetchType.LAZY)
833
@LazyGroup("binary")
834
@Lob
835
private byte[] attachments;
836
837
// Constructors, getters, setters
838
}
839
```
840
841
## Mapping Best Practices
842
843
### Performance Considerations
844
845
- Use `@Cache` judiciously on frequently read, infrequently modified entities
846
- Implement `@BatchSize` for associations to avoid N+1 queries
847
- Use `@LazyGroup` to separate rarely accessed large properties
848
- Consider `@DynamicUpdate` for entities with many nullable columns
849
850
### Natural Identifiers
851
852
- Use `@NaturalId` for business keys (username, email, etc.)
853
- Enable `@NaturalIdCache` for frequently accessed natural IDs
854
- Keep natural IDs immutable when possible
855
856
### Custom Types
857
858
- Implement custom types for domain-specific value objects
859
- Use `@Type` for complex mappings that don't fit standard types
860
- Consider `@Formula` for computed properties that don't need persistence