HHH-11290 - Migrate all documentation snippets that derive the source code from extras instead of actual Unit Tests
Fixed in the Natural Id chapter
This commit is contained in:
parent
64b16fdf5e
commit
c39a337418
|
@ -1,11 +0,0 @@
|
||||||
@Entity
|
|
||||||
public class Person {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
@NaturalId( mutable = true )
|
|
||||||
private String ssn;
|
|
||||||
|
|
||||||
...
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
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" );
|
|
|
@ -1,12 +0,0 @@
|
||||||
@Entity
|
|
||||||
@NaturalIdCache
|
|
||||||
public class Company {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
@NaturalId
|
|
||||||
private String taxIdentifier;
|
|
||||||
|
|
||||||
...
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
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();
|
|
|
@ -1,15 +0,0 @@
|
||||||
@Entity
|
|
||||||
public class Course {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
@NaturalId
|
|
||||||
@ManyToOne
|
|
||||||
private Department department;
|
|
||||||
|
|
||||||
@NaturalId
|
|
||||||
private String code;
|
|
||||||
|
|
||||||
...
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
@Entity
|
|
||||||
public class Company {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
@NaturalId
|
|
||||||
private String taxIdentifier;
|
|
||||||
|
|
||||||
...
|
|
||||||
}
|
|
|
@ -1,18 +0,0 @@
|
||||||
@Entity
|
|
||||||
public class PostalCarrier {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
@NaturalId
|
|
||||||
@Embedded
|
|
||||||
private PostalCode postalCode;
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Embeddable
|
|
||||||
public class PostalCode {
|
|
||||||
...
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
Session session = ...;
|
|
||||||
|
|
||||||
Company company = session.bySimpleNaturalId( Company.class )
|
|
||||||
.load( "abc-123-xyz" );
|
|
||||||
|
|
||||||
PostalCarrier carrier = session.bySimpleNaturalId( PostalCarrier.class )
|
|
||||||
.load( new PostalCode(... ) );
|
|
|
@ -1,6 +1,7 @@
|
||||||
[[naturalid]]
|
[[naturalid]]
|
||||||
=== Natural Ids
|
=== Natural Ids
|
||||||
:sourcedir: extras
|
:sourcedir: ../../../../../test/java/org/hibernate/userguide/mapping/identifier
|
||||||
|
:extrasdir: extras
|
||||||
|
|
||||||
Natural ids represent domain model unique identifiers that have a meaning in the real world too.
|
Natural ids represent domain model unique identifiers that have a meaning in the real world too.
|
||||||
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.
|
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.
|
||||||
|
@ -9,29 +10,33 @@ As we will see later, Hibernate provides a dedicated, efficient API for loading
|
||||||
[[naturalid-mapping]]
|
[[naturalid-mapping]]
|
||||||
==== Natural Id Mapping
|
==== Natural Id Mapping
|
||||||
|
|
||||||
Natural ids are defined in terms of one or more persistent attributes.
|
Natural ids are defined in terms of on
|
||||||
|
e or more persistent attributes.
|
||||||
|
|
||||||
|
[[naturalid-simple-basic-attribute-mapping-example]]
|
||||||
.Natural id using single basic attribute
|
.Natural id using single basic attribute
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/natural_id/SimpleBasicNaturalIdMapping.java[]
|
include::{sourcedir}/SimpleNaturalIdTest.java[tags=naturalid-simple-basic-attribute-mapping-example,indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[naturalid-single-embedded-attribute-mapping-example]]
|
||||||
.Natural id using single embedded attribute
|
.Natural id using single embedded attribute
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/natural_id/SimpleCompositeNaturalIdMapping.java[]
|
include::{sourcedir}/CompositeNaturalIdTest.java[tags=naturalid-single-embedded-attribute-mapping-example,indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[naturalid-multiple-attribute-mapping-example]]
|
||||||
.Natural id using multiple persistent attributes
|
.Natural id using multiple persistent attributes
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/natural_id/NonSimpleNaturalIdMapping.java[]
|
include::{sourcedir}/MultipleNaturalIdTest.java[tags=naturalid-multiple-attribute-mapping-example,indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
@ -46,11 +51,22 @@ This is represented by the `org.hibernate.NaturalIdLoadAccess` contract obtained
|
||||||
If the entity does not define a natural id, trying to load an entity by its natural id will throw an exception.
|
If the entity does not define a natural id, trying to load an entity by its natural id will throw an exception.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[naturalid-load-access-example]]
|
||||||
.Using NaturalIdLoadAccess
|
.Using NaturalIdLoadAccess
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/natural_id/NaturalIdLoadAccessUsage.java[]
|
include::{sourcedir}/SimpleNaturalIdTest.java[tags=naturalid-load-access-example,indent=0]
|
||||||
|
----
|
||||||
|
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
include::{sourcedir}/CompositeNaturalIdTest.java[tags=naturalid-load-access-example,indent=0]
|
||||||
|
----
|
||||||
|
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
include::{sourcedir}/MultipleNaturalIdTest.java[tags=naturalid-load-access-example,indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
@ -68,17 +84,26 @@ We will discuss the last method available on NaturalIdLoadAccess ( `setSynchroni
|
||||||
|
|
||||||
Because the `Company` and `PostalCarrier` entities define "simple" natural ids, we can load them as follows:
|
Because the `Company` and `PostalCarrier` entities define "simple" natural ids, we can load them as follows:
|
||||||
|
|
||||||
.Using SimpleNaturalIdLoadAccess
|
[[naturalid-simple-load-access-example]]
|
||||||
|
.Loading by simple natural id
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/natural_id/SimpleNaturalIdLoadAccessUsage.java[]
|
include::{sourcedir}/SimpleNaturalIdTest.java[tags=naturalid-simple-load-access-example,indent=0]
|
||||||
|
----
|
||||||
|
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
include::{sourcedir}/CompositeNaturalIdTest.java[tags=naturalid-simple-load-access-example,indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
Here we see the use of the `org.hibernate.SimpleNaturalIdLoadAccess` contract, obtained via `Session#bySimpleNaturalId().
|
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.
|
`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.
|
Instead, because these _simple_ natural ids are defined based on just one attribute we can directly pass
|
||||||
|
the corresponding natural id attribute value directly to the `load()` and `getReference()` methods.
|
||||||
|
|
||||||
[NOTE]
|
[NOTE]
|
||||||
====
|
====
|
||||||
|
@ -90,18 +115,21 @@ If the entity does not define a natural id, or if the natural id is not of a "si
|
||||||
|
|
||||||
A natural id may be mutable or immutable. By default the `@NaturalId` annotation marks an immutable natural id attribute.
|
A natural id may be mutable or immutable. By default the `@NaturalId` annotation marks an immutable natural id attribute.
|
||||||
An immutable natural id is expected to never change its value.
|
An immutable natural id is expected to never change its value.
|
||||||
|
|
||||||
If the value(s) of the natural id attribute(s) change, `@NaturalId(mutable=true)` should be used instead.
|
If the value(s) of the natural id attribute(s) change, `@NaturalId(mutable=true)` should be used instead.
|
||||||
|
|
||||||
.Mutable natural id
|
[[naturalid-mutable-mapping-example]]
|
||||||
|
.Mutable natural id mapping
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/natural_id/MutableNaturalIdMapping.java[]
|
include::{sourcedir}/MutableNaturalIdTest.java[tags=naturalid-mutable-mapping-example,indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
Within the Session, Hibernate maintains a mapping from natural id values to entity identifiers (PK) values.
|
Within the Session, Hibernate maintains a mapping from natural id values to entity identifiers (PK) values.
|
||||||
If natural ids values changed, it is possible for this mapping to become out of date until a flush occurs.
|
If natural ids values 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 them when the `load()` or `getReference()` methods are executed.
|
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.
|
||||||
To be clear: this is only pertinent for mutable natural ids.
|
To be clear: this is only pertinent for mutable natural ids.
|
||||||
|
|
||||||
|
@ -112,11 +140,12 @@ If an application is certain that none of its mutable natural ids already associ
|
||||||
This will force Hibernate to circumvent the checking of mutable natural ids.
|
This will force Hibernate to circumvent the checking of mutable natural ids.
|
||||||
====
|
====
|
||||||
|
|
||||||
|
[[naturalid-mutable-synchronized-example]]
|
||||||
.Mutable natural id synchronization use-case
|
.Mutable natural id synchronization use-case
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/natural_id/MutableNaturalIdSynchronization.java[]
|
include::{sourcedir}/MutableNaturalIdTest.java[tags=naturalid-mutable-synchronized-example,indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
@ -127,6 +156,6 @@ Not only can this NaturalId-to-PK resolution be cached in the Session, but we ca
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{sourcedir}/natural_id/NaturalIdCaching.java[]
|
include::{sourcedir}/CacheableNaturalIdTest.java[tags=naturalid-cacheable-mapping-example,indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
|
@ -48,6 +48,8 @@ According to JPA, the valid types for these attributes are limited to:
|
||||||
* `long` or `Long`
|
* `long` or `Long`
|
||||||
* `java.sql.Timestamp`
|
* `java.sql.Timestamp`
|
||||||
|
|
||||||
|
However, Hibernate allows you to use even Java 8 Date/Time types, such as `Instant`.
|
||||||
|
|
||||||
[[locking-optimistic-version-example]]
|
[[locking-optimistic-version-example]]
|
||||||
.`@Version` annotation mapping
|
.`@Version` annotation mapping
|
||||||
====
|
====
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.userguide.mapping.identifier;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.annotations.NaturalId;
|
||||||
|
import org.hibernate.annotations.NaturalIdCache;
|
||||||
|
import org.hibernate.cache.ehcache.EhCacheRegionFactory;
|
||||||
|
import org.hibernate.cfg.AvailableSettings;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class CacheableNaturalIdTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Book.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
protected void addConfigOptions(Map options) {
|
||||||
|
options.put( AvailableSettings.USE_SECOND_LEVEL_CACHE, Boolean.TRUE.toString() );
|
||||||
|
options.put( AvailableSettings.CACHE_REGION_FACTORY, EhCacheRegionFactory.class.getName() );
|
||||||
|
options.put( AvailableSettings.USE_QUERY_CACHE, Boolean.TRUE.toString() );
|
||||||
|
options.put( AvailableSettings.GENERATE_STATISTICS, Boolean.TRUE.toString() );
|
||||||
|
options.put( AvailableSettings.CACHE_REGION_PREFIX, "" );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Book book = new Book();
|
||||||
|
book.setId( 1L );
|
||||||
|
book.setTitle( "High-Performance Java Persistence" );
|
||||||
|
book.setAuthor( "Vlad Mihalcea" );
|
||||||
|
book.setIsbn( "978-9730228236" );
|
||||||
|
|
||||||
|
entityManager.persist( book );
|
||||||
|
} );
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
//tag::naturalid-cacheable-load-access-example[]
|
||||||
|
Book book = entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.bySimpleNaturalId( Book.class )
|
||||||
|
.load( "978-9730228236" );
|
||||||
|
//end::naturalid-cacheable-load-access-example[]
|
||||||
|
|
||||||
|
assertEquals("High-Performance Java Persistence", book.getTitle());
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::naturalid-cacheable-mapping-example[]
|
||||||
|
@Entity(name = "Book")
|
||||||
|
@NaturalIdCache
|
||||||
|
public static class Book {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
@NaturalId
|
||||||
|
private String isbn;
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::naturalid-cacheable-mapping-example[]
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(String author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIsbn() {
|
||||||
|
return isbn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsbn(String isbn) {
|
||||||
|
this.isbn = isbn;
|
||||||
|
}
|
||||||
|
//tag::naturalid-cacheable-mapping-example[]
|
||||||
|
}
|
||||||
|
//end::naturalid-cacheable-mapping-example[]
|
||||||
|
}
|
|
@ -0,0 +1,193 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.userguide.mapping.identifier;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.Embedded;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.annotations.NaturalId;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class CompositeNaturalIdTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Book.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Book book = new Book();
|
||||||
|
book.setId( 1L );
|
||||||
|
book.setTitle( "High-Performance Java Persistence" );
|
||||||
|
book.setAuthor( "Vlad Mihalcea" );
|
||||||
|
book.setIsbn( new Isbn(
|
||||||
|
"973022823X",
|
||||||
|
"978-9730228236"
|
||||||
|
) );
|
||||||
|
|
||||||
|
entityManager.persist( book );
|
||||||
|
} );
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
//tag::naturalid-simple-load-access-example[]
|
||||||
|
|
||||||
|
Book book = entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.bySimpleNaturalId( Book.class )
|
||||||
|
.load(
|
||||||
|
new Isbn(
|
||||||
|
"973022823X",
|
||||||
|
"978-9730228236"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
//end::naturalid-simple-load-access-example[]
|
||||||
|
|
||||||
|
assertEquals("High-Performance Java Persistence", book.getTitle());
|
||||||
|
} );
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
//tag::naturalid-load-access-example[]
|
||||||
|
|
||||||
|
Book book = entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.byNaturalId( Book.class )
|
||||||
|
.using(
|
||||||
|
"isbn",
|
||||||
|
new Isbn(
|
||||||
|
"973022823X",
|
||||||
|
"978-9730228236"
|
||||||
|
) )
|
||||||
|
.load();
|
||||||
|
//end::naturalid-load-access-example[]
|
||||||
|
|
||||||
|
assertEquals("High-Performance Java Persistence", book.getTitle());
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::naturalid-single-embedded-attribute-mapping-example[]
|
||||||
|
@Entity(name = "Book")
|
||||||
|
public static class Book {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
@NaturalId
|
||||||
|
@Embedded
|
||||||
|
private Isbn isbn;
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::naturalid-single-embedded-attribute-mapping-example[]
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(String author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Isbn getIsbn() {
|
||||||
|
return isbn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsbn(Isbn isbn) {
|
||||||
|
this.isbn = isbn;
|
||||||
|
}
|
||||||
|
//tag::naturalid-single-embedded-attribute-mapping-example[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Embeddable
|
||||||
|
public static class Isbn implements Serializable {
|
||||||
|
|
||||||
|
private String isbn10;
|
||||||
|
|
||||||
|
private String isbn13;
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::naturalid-single-embedded-attribute-mapping-example[]
|
||||||
|
|
||||||
|
public Isbn() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Isbn(String isbn10, String isbn13) {
|
||||||
|
this.isbn10 = isbn10;
|
||||||
|
this.isbn13 = isbn13;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIsbn10() {
|
||||||
|
return isbn10;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsbn10(String isbn10) {
|
||||||
|
this.isbn10 = isbn10;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIsbn13() {
|
||||||
|
return isbn13;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsbn13(String isbn13) {
|
||||||
|
this.isbn13 = isbn13;
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::naturalid-single-embedded-attribute-mapping-example[]
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( o == null || getClass() != o.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Isbn isbn = (Isbn) o;
|
||||||
|
return Objects.equals( isbn10, isbn.isbn10 ) &&
|
||||||
|
Objects.equals( isbn13, isbn.isbn13 );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash( isbn10, isbn13 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//end::naturalid-single-embedded-attribute-mapping-example[]
|
||||||
|
}
|
|
@ -0,0 +1,185 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.userguide.mapping.identifier;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Objects;
|
||||||
|
import javax.persistence.Embeddable;
|
||||||
|
import javax.persistence.Embedded;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.annotations.NaturalId;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class MultipleNaturalIdTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Book.class,
|
||||||
|
Publisher.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Publisher publisher = new Publisher();
|
||||||
|
publisher.setId( 1L );
|
||||||
|
publisher.setName( "Amazon" );
|
||||||
|
entityManager.persist( publisher );
|
||||||
|
|
||||||
|
Book book = new Book();
|
||||||
|
book.setId( 1L );
|
||||||
|
book.setTitle( "High-Performance Java Persistence" );
|
||||||
|
book.setAuthor( "Vlad Mihalcea" );
|
||||||
|
book.setProductNumber( "973022823X" );
|
||||||
|
book.setPublisher( publisher );
|
||||||
|
|
||||||
|
entityManager.persist( book );
|
||||||
|
} );
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Publisher publisher = entityManager.getReference( Publisher.class, 1L );
|
||||||
|
//tag::naturalid-load-access-example[]
|
||||||
|
|
||||||
|
Book book = entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.byNaturalId( Book.class )
|
||||||
|
.using("productNumber", "973022823X")
|
||||||
|
.using("publisher", publisher)
|
||||||
|
.load();
|
||||||
|
//end::naturalid-load-access-example[]
|
||||||
|
|
||||||
|
assertEquals("High-Performance Java Persistence", book.getTitle());
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::naturalid-multiple-attribute-mapping-example[]
|
||||||
|
@Entity(name = "Book")
|
||||||
|
public static class Book {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
@NaturalId
|
||||||
|
private String productNumber;
|
||||||
|
|
||||||
|
@NaturalId
|
||||||
|
@ManyToOne(fetch = FetchType.LAZY)
|
||||||
|
private Publisher publisher;
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::naturalid-multiple-attribute-mapping-example[]
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(String author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProductNumber() {
|
||||||
|
return productNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProductNumber(String productNumber) {
|
||||||
|
this.productNumber = productNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Publisher getPublisher() {
|
||||||
|
return publisher;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublisher(Publisher publisher) {
|
||||||
|
this.publisher = publisher;
|
||||||
|
}
|
||||||
|
//tag::naturalid-multiple-attribute-mapping-example[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Publisher")
|
||||||
|
public static class Publisher implements Serializable {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::naturalid-multiple-attribute-mapping-example[]
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::naturalid-multiple-attribute-mapping-example[]
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( o == null || getClass() != o.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Publisher publisher = (Publisher) o;
|
||||||
|
return Objects.equals( id, publisher.id ) &&
|
||||||
|
Objects.equals( name, publisher.name );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash( id, name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//end::naturalid-multiple-attribute-mapping-example[]
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.userguide.mapping.identifier;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.annotations.NaturalId;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class MutableNaturalIdTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Author.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Author author = new Author();
|
||||||
|
author.setId( 1L );
|
||||||
|
author.setName( "John Doe" );
|
||||||
|
author.setEmail( "john@acme.com" );
|
||||||
|
|
||||||
|
entityManager.persist( author );
|
||||||
|
} );
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
//tag::naturalid-mutable-synchronized-example[]
|
||||||
|
//tag::naturalid-mutable-example[]
|
||||||
|
Author author = entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.bySimpleNaturalId( Author.class )
|
||||||
|
.load( "john@acme.com" );
|
||||||
|
//end::naturalid-mutable-example[]
|
||||||
|
|
||||||
|
author.setEmail( "john.doe@acme.com" );
|
||||||
|
|
||||||
|
assertNull(
|
||||||
|
entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.bySimpleNaturalId( Author.class )
|
||||||
|
.setSynchronizationEnabled( false )
|
||||||
|
.load( "john.doe@acme.com" )
|
||||||
|
);
|
||||||
|
|
||||||
|
assertSame( author,
|
||||||
|
entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.bySimpleNaturalId( Author.class )
|
||||||
|
.setSynchronizationEnabled( true )
|
||||||
|
.load( "john.doe@acme.com" )
|
||||||
|
);
|
||||||
|
//end::naturalid-mutable-example[]
|
||||||
|
|
||||||
|
//end::naturalid-mutable-synchronized-example[]
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::naturalid-mutable-mapping-example[]
|
||||||
|
@Entity(name = "Author")
|
||||||
|
public static class Author {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NaturalId(mutable = true)
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::naturalid-mutable-mapping-example[]
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::naturalid-mutable-mapping-example[]
|
||||||
|
}
|
||||||
|
//end::naturalid-mutable-mapping-example[]
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||||
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||||
|
*/
|
||||||
|
package org.hibernate.userguide.mapping.identifier;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
|
||||||
|
import org.hibernate.Session;
|
||||||
|
import org.hibernate.annotations.NaturalId;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class SimpleNaturalIdTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Book.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Book book = new Book();
|
||||||
|
book.setId( 1L );
|
||||||
|
book.setTitle( "High-Performance Java Persistence" );
|
||||||
|
book.setAuthor( "Vlad Mihalcea" );
|
||||||
|
book.setIsbn( "978-9730228236" );
|
||||||
|
|
||||||
|
entityManager.persist( book );
|
||||||
|
} );
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
//tag::naturalid-simple-load-access-example[]
|
||||||
|
Book book = entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.bySimpleNaturalId( Book.class )
|
||||||
|
.load( "978-9730228236" );
|
||||||
|
//end::naturalid-simple-load-access-example[]
|
||||||
|
|
||||||
|
assertEquals("High-Performance Java Persistence", book.getTitle());
|
||||||
|
} );
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
//tag::naturalid-load-access-example[]
|
||||||
|
Book book = entityManager
|
||||||
|
.unwrap(Session.class)
|
||||||
|
.byNaturalId( Book.class )
|
||||||
|
.using( "isbn", "978-9730228236" )
|
||||||
|
.load();
|
||||||
|
//end::naturalid-load-access-example[]
|
||||||
|
|
||||||
|
assertEquals("High-Performance Java Persistence", book.getTitle());
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::naturalid-simple-basic-attribute-mapping-example[]
|
||||||
|
@Entity(name = "Book")
|
||||||
|
public static class Book {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
@NaturalId
|
||||||
|
private String isbn;
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::naturalid-simple-basic-attribute-mapping-example[]
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAuthor() {
|
||||||
|
return author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthor(String author) {
|
||||||
|
this.author = author;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIsbn() {
|
||||||
|
return isbn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsbn(String isbn) {
|
||||||
|
this.isbn = isbn;
|
||||||
|
}
|
||||||
|
//tag::naturalid-simple-basic-attribute-mapping-example[]
|
||||||
|
}
|
||||||
|
//end::naturalid-simple-basic-attribute-mapping-example[]
|
||||||
|
}
|
Loading…
Reference in New Issue