diff --git a/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/Natural_Id.xml b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/Natural_Id.xml
index b5a1933952..fe4cfab3a2 100644
--- a/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/Natural_Id.xml
+++ b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/Natural_Id.xml
@@ -9,12 +9,151 @@
version="5.0"
xml:lang="en"
xmlns="http://docbook.org/ns/docbook"
- >
+ xmlns:xi="http://www.w3.org/2001/XInclude">
Natural Ids
+
- * simple
- * composite
- * caching
- * apis
+ Natural ids represent unique identifiers that naturally exist within your domain model. Even if
+ a natural id does not make a good primary key, it still is useful to tell Hibernate about it.
+ As we will see later, Hibernate provides a dedicated, efficient API for loading and entity by its natural-id
+ much like it offers for loading by identifier (PK).
+
+
+ Natural Id Mapping
+
+
+ Natural ids are defined in terms of one or more persistent attributes.
+
+
+
+ Natural id using single basic attribute
+
+
+
+
+ Natural id using single embedded attribute
+
+
+
+
+ Natural id using multiple persistent attributes
+
+
+
+
+
+
+ Natural Id API
+
+
+ As stated before, Hibernate provides an API for loading entities by natural id. This is represented by the
+ org.hibernate.NaturalIdLoadAccess contract obtained via
+ Session#byNaturalId. If the entity does not define a natural id, an exception
+ will be thrown there.
+
+
+
+ Using NaturalIdLoadAccess
+
+
+
+
+ NaturalIdLoadAccess offers 2 distinct methods for obtaining the entity:
+
+
+
+ load - obtains a reference to the entity, making sure
+ that the entity state is initialized.
+
+
+
+
+ getReference - obtains a reference to the entity. The state
+ may or may not be initialized. If the entity is associated with the Session already,
+ that reference (loaded or not) is returned; else if the entity supports proxy
+ generation, an uninitialized proxy is generated and returned; otherwise
+ the entity is loaded from the database and returned.
+
+
+
+
+
+
+ NaturalIdLoadAccess also allows to request locking for the load. We might use that to load an
+ entity by natural id and at the same time apply a pessimistic lock. For additional details on locking,
+ see the Hibernate User Guide.
+
+
+
+ We will discuss the last method available on NaturalIdLoadAccess
+ (setSynchronizationEnabled) in .
+
+
+
+ Because the Company and PostalCarrier entities define "simple" natural ids, we also allow simplified
+ access to load them based on the natural ids.
+
+
+
+ Using SimpleNaturalIdLoadAccess
+
+
+
+
+ Here we see the use of the org.hibernate.SimpleNaturalIdLoadAccess
+ contract, obtained via Session#bySimpleNaturalId. SimpleNaturalIdLoadAccess is similar
+ to NaturalIdLoadAccess except that it does not define the using method. Instead,
+ because these "simple" natural ids are defined based on just one attribute we can directly pass the
+ corresponding value of that natural id attribute directly to the load
+ and getReference methods. If the entity does not define a natural id or if the
+ natural id it does define is not simple, an exception will be thrown there.
+
+
+
+
+ Natural Id - Mutability and Caching
+
+ A natural id may be mutable or immutable. By default @NaturalId marks
+ an immutable natural id. An immutable natural id is expected to never change values.
+ If the values of the natural id attribute(s) can change, @NaturalId(mutable=true)
+ should be used instead.
+
+
+
+ Mutable natural id
+
+
+
+
+ Within the Session, Hibernate maintains a mapping from natural id values to pk values. If natural ids
+ values have changed it is possible for this mapping to become out of date until a flush occurs. To work
+ around this condition, Hibernate will attempt to discover any such pending changes and adjust for them
+ when the load or getReference method is executed. To
+ be clear: this is only pertinent for mutable natural ids.
+
+
+
+ This "discovery and adjustment" have a performance impact. If an application is certain that none of its
+ mutable natural ids already associated with the Session have changed, it can disable that checking by
+ calling setSynchronizationEnabled(false) (the default is true). This will force
+ Hibernate to circumvent the checking of mutable natural ids.
+
+
+
+ Mutable natural id synchronization use-case
+
+
+
+
+ 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.
+
+
+
+ Natural id caching
+
+
+
+
\ No newline at end of file
diff --git a/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/MutableNaturalIdMapping.java b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/MutableNaturalIdMapping.java
new file mode 100644
index 0000000000..ef4c94375e
--- /dev/null
+++ b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/MutableNaturalIdMapping.java
@@ -0,0 +1,8 @@
+@Entity
+public class Person {
+ @Id
+ private Integer id;
+ @NaturalId(mutable=true)
+ private String ssn;
+ ...
+}
\ No newline at end of file
diff --git a/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/MutableNaturalIdSynchronization.java b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/MutableNaturalIdSynchronization.java
new file mode 100644
index 0000000000..d3945140fa
--- /dev/null
+++ b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/MutableNaturalIdSynchronization.java
@@ -0,0 +1,17 @@
+Session session = ...;
+
+Person person = session.bySimpleNaturalId( Person.class )
+ .load( "123-45-6789" );
+person.setSsn( "987-65-4321" );
+
+...
+
+// returns null!
+person = session.bySimpleNaturalId( Person.class )
+ .setSynchronizationEnabled( false )
+ .load( "987-65-4321" );
+
+// returns correctly!
+person = session.bySimpleNaturalId( Person.class )
+ .setSynchronizationEnabled( true )
+ .load( "987-65-4321" );
\ No newline at end of file
diff --git a/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/NaturalIdCaching.java b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/NaturalIdCaching.java
new file mode 100644
index 0000000000..5c5fd193c4
--- /dev/null
+++ b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/NaturalIdCaching.java
@@ -0,0 +1,9 @@
+@Entity
+@NaturalIdCache
+public class Company {
+ @Id
+ private Integer id;
+ @NaturalId
+ private String taxIdentifier;
+ ...
+}
\ No newline at end of file
diff --git a/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/NaturalIdLoadAccessUsage.java b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/NaturalIdLoadAccessUsage.java
new file mode 100644
index 0000000000..ab61f73f72
--- /dev/null
+++ b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/NaturalIdLoadAccessUsage.java
@@ -0,0 +1,15 @@
+Session session = ...;
+
+Company company = session.byNaturalId( Company.class )
+ .using( "taxIdentifier", "abc-123-xyz" )
+ .load();
+
+PostalCarrier carrier = session.byNaturalId( PostalCarrier.class )
+ .using( "postalCode", new PostalCode( ... ) )
+ .load();
+
+Department department = ...;
+Course course = session.byNaturalId( Course.class )
+ .using( "department", department )
+ .using( "code", "101" )
+ .load();
\ No newline at end of file
diff --git a/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/NonSimpleNaturalIdMapping.java b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/NonSimpleNaturalIdMapping.java
new file mode 100644
index 0000000000..4e5baa6cbb
--- /dev/null
+++ b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/NonSimpleNaturalIdMapping.java
@@ -0,0 +1,11 @@
+@Entity
+public class Course {
+ @Id
+ private Integer id;
+ @NaturalId
+ @ManyToOne
+ private Department department;
+ @NaturalId
+ private String code;
+ ...
+}
\ No newline at end of file
diff --git a/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/SimpleBasicNaturalIdMapping.java b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/SimpleBasicNaturalIdMapping.java
new file mode 100644
index 0000000000..6cf78d4f59
--- /dev/null
+++ b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/SimpleBasicNaturalIdMapping.java
@@ -0,0 +1,8 @@
+@Entity
+public class Company {
+ @Id
+ private Integer id;
+ @NaturalId
+ private String taxIdentifier;
+ ...
+}
\ No newline at end of file
diff --git a/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/SimpleCompositeNaturalIdMapping.java b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/SimpleCompositeNaturalIdMapping.java
new file mode 100644
index 0000000000..204ea5b372
--- /dev/null
+++ b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/SimpleCompositeNaturalIdMapping.java
@@ -0,0 +1,15 @@
+@Entity
+public class PostalCarrier {
+ @Id
+ private Integer id;
+ @NaturalId
+ @Embedded
+ private PostalCode postalCode;
+ ...
+
+}
+
+@Embeddable
+public class PostalCode {
+ ...
+}
diff --git a/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/SimpleNaturalIdLoadAccessUsage.java b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/SimpleNaturalIdLoadAccessUsage.java
new file mode 100644
index 0000000000..892ee549a6
--- /dev/null
+++ b/documentation/src/main/docbook/mappingGuide/en-US/chapters/natural_id/extras/SimpleNaturalIdLoadAccessUsage.java
@@ -0,0 +1,7 @@
+Session session = ...;
+
+Company company = session.bySimpleNaturalId( Company.class )
+ .load( "abc-123-xyz" );
+
+PostalCarrier carrier = session.bySimpleNaturalId( PostalCarrier.class )
+ .load( new PostalCode( ... ) );
\ No newline at end of file
diff --git a/documentation/status.md b/documentation/status.md
index b5c95d59b2..5364b12289 100644
--- a/documentation/status.md
+++ b/documentation/status.md
@@ -4,20 +4,23 @@ Status of the documentation overhaul (5.0 version)
Overall the plan is to define 3 DocBook-based guides. The intention is for this document to serve
as an outline of the work and a status of what still needs done.
+NOTE : entries marked with strike-through indicate that the content is believed to be done; review
+would still be appreciated.
+
User Guide
==========
Covers reference topics targeting users.
-* Prefix (done)
-* Architecture (done)
-* DomainModel (done)
-* Bootstrap (done)
-* PersistenceContext (done)
-* Database_Access (done)
-* Transactions (done)
-* JNDI (done)
+* Prefix
+* Architecture
+* DomainModel
+* Bootstrap
+* PersistenceContext
+* Database_Access
+* Transactions
+* JNDI
* Locking (needs some work)
* Fetching (needs some work)
* Batching (needs lot of work - not started - open questions)
@@ -28,7 +31,7 @@ Covers reference topics targeting users.
* Native_Queries (needs lots of work)
* Multi_Tenancy (needs some work)
* OSGi (right place for this?)
-* Envers
+* Envers (right place for this?)
* Portability (needs some work)
@@ -39,15 +42,15 @@ Covers mapping domain model to database. Note that a lot of the "not started" c
matter of pulling that content in and better organizing it.
-* Prefix (done)
-* Data_Categorizations (done)
-* Basic_Types (done)
-* Composition (done)
-* Collection (needs some work)
+* Prefix
+* Data_Categorizations
+* Basic_Types
+* Composition
+* Collection (needs some work)
* Entity (needs some work)
* Secondary_Tables (not started)
* Identifiers (mostly done - needs "derived id" stuff documented)
-* Natural_Id (not started)
+* Natural_Id
* Associations (not started)
* Attribute_Access (not started)
* Mapping_Overrides - AttributeOverrides/AssociationOverrides (not started)