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)