99 version =" 5.0"
1010 xml : lang =" en"
1111 xmlns =" http://docbook.org/ns/docbook"
12- >
12+ xmlns : xi = " http://www.w3.org/2001/XInclude " >
1313 <title >Natural Ids</title >
14+
1415 <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).
1920 </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 >
20159</chapter >
0 commit comments