You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Natural ids represent domain model unique identifiers that have a meaning in the real world too.
10
+
Natural ids are unique identifiers in the domain model that have a meaning in the real world too.
10
11
Even if a natural id does not make a good primary key (surrogate keys being usually preferred), it's still useful to tell Hibernate about it.
11
-
As we will see later, Hibernate provides a dedicated, efficient API for loading an entity by its natural id much like it offers for loading by identifier (PK).
12
-
13
-
[IMPORTANT]
14
-
====
15
-
All values used in a natural id must be non-nullable.
16
-
17
-
For natural id mappings using a to-one association, this precludes the use of not-found
18
-
mappings which effectively define a nullable mapping.
19
-
====
12
+
As we will see <<find-by-natural-id,later>>, Hibernate provides an efficient means for loading an entity by its natural id much like it offers for loading by identifier (PK).
As stated before, Hibernate provides an API for loading entities by their associated natural id.
57
-
This is represented by the `org.hibernate.NaturalIdLoadAccess` contract obtained via Session#byNaturalId.
46
+
Natural ids defined using multiple persistent attributes may also define a link:{doc-javadoc-url}org/hibernate/annotations/NaturalIdClass.html[`@NaturalIdClass`] which can be used for <<find-by-natural-id,find operations>>.
58
47
59
-
[NOTE]
60
-
====
61
-
If the entity does not define a natural id, trying to load an entity by its natural id will throw an exception.
NaturalIdLoadAccess offers 2 distinct methods for obtaining the entity:
84
76
85
-
`load()`:: obtains a reference to the entity, making sure that the entity state is initialized.
86
-
`getReference()`:: obtains a reference to the entity. The state may or may not be initialized.
87
-
If the entity is already associated with the current running Session, that reference (loaded or not) is returned.
88
-
If the entity is not loaded in the current Session and the entity supports proxy generation, an uninitialized proxy is generated and returned, otherwise the entity is loaded from the database and returned.
89
77
90
-
`NaturalIdLoadAccess` allows loading an entity by natural id and at the same time applies a pessimistic lock.
91
-
For additional details on locking, see the <<chapters/locking/Locking.adoc#locking,Locking>> chapter.
92
78
93
-
We will discuss the last method available on NaturalIdLoadAccess ( `setSynchronizationEnabled()` ) in <<naturalid-mutability-caching>>.
94
79
95
-
Because the `Book` entities in the first two examples define "simple" natural ids, we can load them as follows:
96
80
97
-
[[naturalid-simple-load-access-example]]
98
-
.Loading by simple natural id
81
+
82
+
83
+
84
+
85
+
86
+
87
+
88
+
89
+
90
+
91
+
92
+
[[natural-id-caching]]
93
+
==== Natural id resolution caching
94
+
95
+
Within the Session, Hibernate maintains a cross reference of the resolutions from natural id values to entity identifier (PK) values.
96
+
We can also have this value resolution cached in the second level cache if second level caching is enabled.
Think carefully before caching resolutions for natural ids which are partially or fully <<natural-id-mutability,mutable>> in the second level cache as this will often have a negative impact on performance.
109
110
====
110
111
111
-
Here we see the use of the `org.hibernate.SimpleNaturalIdLoadAccess` contract,
112
-
obtained via `Session#bySimpleNaturalId()`.
113
112
114
-
`SimpleNaturalIdLoadAccess` is similar to `NaturalIdLoadAccess` except that it does not define the using method.
115
-
Instead, because these _simple_ natural ids are defined based on just one attribute we can directly pass
116
-
the corresponding natural id attribute value directly to the `load()` and `getReference()` methods.
113
+
114
+
[[find-by-natural-id]]
115
+
[[naturalid-api]]
116
+
==== Loading by natural id
117
+
118
+
Hibernate provides a means to load one or more entities by natural id using the `KeyType.NATURAL` `FindOption` passed to `find()` or `findMultiple()`.
117
119
118
120
[NOTE]
119
121
====
120
-
If the entity does not define a natural id, or if the natural id is not of a "simple" type, an exception will be thrown there.
122
+
Hibernate historically offered the dedicated `byNaturalId()`, `bySimpleNaturalId()` and `byMultipleNaturalId()` APIs for loading one or more entities by natural id using its legacy "load access" approach. However, with JPA 3.2 and the introduction of `FindOption`, etc., these "load access" approaches are considered deprecated and are not discussed here.
121
123
====
122
124
123
-
[[naturalid-mutability-caching]]
124
-
==== Natural Id - Mutability and Caching
125
-
126
-
A natural id may be mutable or immutable. By default the `@NaturalId` annotation marks an immutable natural id attribute.
127
-
An immutable natural id is expected to never change its value.
128
-
129
-
If the value(s) of the natural id attribute(s) change, `@NaturalId(mutable = true)` should be used instead.
Within the Session, Hibernate maintains a mapping from natural id values to entity identifiers (PK) values.
141
-
If natural ids values changed, it is possible for this mapping to become out of date until a flush occurs.
135
+
When loading by natural id, the type of value accepted depends on the definition of the natural id.
142
136
143
-
To work around this condition, Hibernate will attempt to discover any such pending changes and adjust them when the `load()` or `getReference()` methods are executed.
144
-
To be clear: this is only pertinent for mutable natural ids.
137
+
* For single-attribute natural ids, whether defined by a basic or embedded type, the attribute type should be used.
138
+
* For multi-attribute natural ids, Hibernate will accept a number of forms:
139
+
140
+
** If a link:{doc-javadoc-url}org/hibernate/annotations/NaturalIdClass.html[`@NaturalIdClass`] is defined, an instance of the natural id class may be used.
141
+
** A `List` of the individual attribute values, ordered alphabetically by name, may be used.
142
+
** A `Map` of the individual attribute values, keyed by the attribute name, may be used.
143
+
144
+
There are a few differences to be aware of when loading by natural id compared to loading by primary key. Most importantly, if the natural id is mutable and its values have changed, it is possible for the resolution caching to become out of date until a flush occurs resulting in incorrect results.
145
+
To work around this condition, Hibernate will attempt to discover any such pending changes and adjust them prior to performing the load.
145
146
146
147
[IMPORTANT]
147
148
====
148
-
This _discovery and adjustment_ have a performance impact.
149
-
If you are certain that none of the mutable natural ids already associated with the current `Session` have changed, you can disable this checking by calling `setSynchronizationEnabled(false)` (the default is `true`).
150
-
This will force Hibernate to circumvent the checking of mutable natural ids.
149
+
This _discovery and adjustment_ (synchronization) has a performance impact.
150
+
If you are certain that none of the mutable natural ids already associated with the current `Session` have changed, you can disable this using the `NaturalIdSynchronization.DISABLED` option which will force Hibernate to skip the checking of mutable natural ids.
151
+
To be clear: this is only pertinent for mutable natural ids.
Not only can this NaturalId-to-PK resolution be cached in the Session, but we can also have it cached in the second-level cache if second level caching is enabled.
0 commit comments