9
9
version =" 5.0"
10
10
xml : lang =" en"
11
11
xmlns =" http://docbook.org/ns/docbook"
12
- >
12
+ xmlns : xi = " http://www.w3.org/2001/XInclude " >
13
13
<title >Natural Ids</title >
14
+
14
15
<para >
15
- * simple
16
- * composite
17
- * caching
18
- * apis
16
+ Natural ids represent unique identifiers that naturally exist within your domain model. Even if
17
+ a natural id does not make a good primary key, it still is useful to tell Hibernate about it.
18
+ As we will see later, Hibernate provides a dedicated, efficient API for loading and entity by its natural-id
19
+ much like it offers for loading by identifier (PK).
19
20
</para >
21
+
22
+ <section xml : id =" naturalid-mapping" >
23
+ <title >Natural Id Mapping</title >
24
+
25
+ <para >
26
+ Natural ids are defined in terms of one or more persistent attributes.
27
+ </para >
28
+
29
+ <example >
30
+ <title >Natural id using single basic attribute</title >
31
+ <programlisting role =" JAVA" ><xi : include href =" extras/SimpleBasicNaturalIdMapping.java" parse =" text" /></programlisting >
32
+ </example >
33
+
34
+ <example >
35
+ <title >Natural id using single embedded attribute</title >
36
+ <programlisting role =" JAVA" ><xi : include href =" extras/SimpleCompositeNaturalIdMapping.java" parse =" text" /></programlisting >
37
+ </example >
38
+
39
+ <example >
40
+ <title >Natural id using multiple persistent attributes</title >
41
+ <programlisting role =" JAVA" ><xi : include href =" extras/NonSimpleNaturalIdMapping.java" parse =" text" /></programlisting >
42
+ </example >
43
+
44
+ </section >
45
+
46
+ <section xml : id =" naturalid-api" >
47
+ <title >Natural Id API</title >
48
+
49
+ <para >
50
+ As stated before, Hibernate provides an API for loading entities by natural id. This is represented by the
51
+ <interfacename >org.hibernate.NaturalIdLoadAccess</interfacename > contract obtained via
52
+ <methodname >Session#byNaturalId</methodname >. If the entity does not define a natural id, an exception
53
+ will be thrown there.
54
+ </para >
55
+
56
+ <example >
57
+ <title >Using NaturalIdLoadAccess</title >
58
+ <programlisting role =" JAVA" ><xi : include href =" extras/NaturalIdLoadAccessUsage.java" parse =" text" /></programlisting >
59
+ </example >
60
+
61
+ <para >
62
+ NaturalIdLoadAccess offers 2 distinct methods for obtaining the entity:
63
+ <itemizedlist >
64
+ <listitem >
65
+ <para >
66
+ <methodname >load</methodname > - obtains a reference to the entity, making sure
67
+ that the entity state is initialized.
68
+ </para >
69
+ </listitem >
70
+ <listitem >
71
+ <para >
72
+ <methodname >getReference</methodname > - obtains a reference to the entity. The state
73
+ may or may not be initialized. If the entity is associated with the Session already,
74
+ that reference (loaded or not) is returned; else if the entity supports proxy
75
+ generation, an uninitialized proxy is generated and returned; otherwise
76
+ the entity is loaded from the database and returned.
77
+ </para >
78
+ </listitem >
79
+ </itemizedlist >
80
+ </para >
81
+
82
+ <para >
83
+ NaturalIdLoadAccess also allows to request locking for the load. We might use that to load an
84
+ entity by natural id and at the same time apply a pessimistic lock. For additional details on locking,
85
+ see the <citetitle >Hibernate User Guide</citetitle >.
86
+ </para >
87
+
88
+ <para >
89
+ We will discuss the last method available on NaturalIdLoadAccess
90
+ (<methodname >setSynchronizationEnabled</methodname >) in <xref linkend =" naturalid-mutability-caching" />.
91
+ </para >
92
+
93
+ <para >
94
+ Because the Company and PostalCarrier entities define "simple" natural ids, we also allow simplified
95
+ access to load them based on the natural ids.
96
+ </para >
97
+
98
+ <example >
99
+ <title >Using SimpleNaturalIdLoadAccess</title >
100
+ <programlisting role =" JAVA" ><xi : include href =" extras/SimpleNaturalIdLoadAccessUsage.java" parse =" text" /></programlisting >
101
+ </example >
102
+
103
+ <para >
104
+ Here we see the use of the <interfacename >org.hibernate.SimpleNaturalIdLoadAccess</interfacename >
105
+ contract, obtained via <methodname >Session#bySimpleNaturalId</methodname >. SimpleNaturalIdLoadAccess is similar
106
+ to NaturalIdLoadAccess except that it does not define the <methodname >using</methodname > method. Instead,
107
+ because these "simple" natural ids are defined based on just one attribute we can directly pass the
108
+ corresponding value of that natural id attribute directly to the <methodname >load</methodname >
109
+ and <methodname >getReference</methodname > methods. If the entity does not define a natural id or if the
110
+ natural id it does define is not simple, an exception will be thrown there.
111
+ </para >
112
+ </section >
113
+
114
+ <section xml : id =" naturalid-mutability-caching" >
115
+ <title >Natural Id - Mutability and Caching</title >
116
+ <para >
117
+ A natural id may be mutable or immutable. By default <literal >@NaturalId</literal > marks
118
+ an immutable natural id. An immutable natural id is expected to never change values.
119
+ If the values of the natural id attribute(s) can change, <literal >@NaturalId(mutable=true)</literal >
120
+ should be used instead.
121
+ </para >
122
+
123
+ <example >
124
+ <title >Mutable natural id</title >
125
+ <programlisting role =" JAVA" ><xi : include href =" extras/MutableNaturalIdMapping.java" parse =" text" /></programlisting >
126
+ </example >
127
+
128
+ <para >
129
+ Within the Session, Hibernate maintains a mapping from natural id values to pk values. If natural ids
130
+ values have changed it is possible for this mapping to become out of date until a flush occurs. To work
131
+ around this condition, Hibernate will attempt to discover any such pending changes and adjust for them
132
+ when the <methodname >load</methodname > or <methodname >getReference</methodname > method is executed. To
133
+ be clear: this is only pertinent for mutable natural ids.
134
+ </para >
135
+
136
+ <para >
137
+ This "discovery and adjustment" have a performance impact. If an application is certain that none of its
138
+ mutable natural ids already associated with the Session have changed, it can disable that checking by
139
+ calling <methodname >setSynchronizationEnabled(false)</methodname > (the default is true). This will force
140
+ Hibernate to circumvent the checking of mutable natural ids.
141
+ </para >
142
+
143
+ <example >
144
+ <title >Mutable natural id synchronization use-case</title >
145
+ <programlisting role =" JAVA" ><xi : include href =" extras/MutableNaturalIdSynchronization.java" parse =" text" /></programlisting >
146
+ </example >
147
+
148
+ <para >
149
+ Not only can this NaturalId-to-PK resolution be cached in the Session, but we can also have it cached in
150
+ the second-level cache if second level caching is enabled.
151
+ </para >
152
+
153
+ <example >
154
+ <title >Natural id caching</title >
155
+ <programlisting role =" JAVA" ><xi : include href =" extras/NaturalIdCaching.java" parse =" text" /></programlisting >
156
+ </example >
157
+
158
+ </section >
20
159
</chapter >
0 commit comments