HHH-11290 - Migrate all documentation snippets that derive the source code from extras instead of actual Unit Tests
Fixed in the Entity chapter
This commit is contained in:
parent
f9cb1d5cb4
commit
87ce2670e7
|
@ -1,7 +1,7 @@
|
||||||
[[entity]]
|
[[entity]]
|
||||||
=== Entity types
|
=== Entity types
|
||||||
:sourcedir-locking: ../../../../../test/java/org/hibernate/userguide/locking
|
:sourcedir-locking: ../../../../../test/java/org/hibernate/userguide/locking
|
||||||
:sourcedir-mapping: ../../../../../test/java/org/hibernate/userguide/mapping/basic
|
:sourcedir-mapping: ../../../../../test/java/org/hibernate/userguide/mapping/
|
||||||
:sourcedir-proxy: ../../../../../test/java/org/hibernate/userguide/proxy
|
:sourcedir-proxy: ../../../../../test/java/org/hibernate/userguide/proxy
|
||||||
:sourcedir-persister: ../../../../../test/java/org/hibernate/userguide/persister
|
:sourcedir-persister: ../../../../../test/java/org/hibernate/userguide/persister
|
||||||
:extrasdir: extras
|
:extrasdir: extras
|
||||||
|
@ -99,11 +99,12 @@ We recommend that you declare consistently-named identifier attributes on persis
|
||||||
|
|
||||||
The placement of the `@Id` annotation marks the <<chapters/domain/access.adoc#access,persistence state access strategy>>.
|
The placement of the `@Id` annotation marks the <<chapters/domain/access.adoc#access,persistence state access strategy>>.
|
||||||
|
|
||||||
.Identifier
|
[[entity-pojo-identifier-mapping-example]]
|
||||||
|
.Identifier mapping
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/Identifier.java[]
|
include::{sourcedir-mapping}/identifier/SimpleEntityTest.java[tag=entity-pojo-identifier-mapping-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
@ -116,11 +117,12 @@ The main piece in mapping the entity is the `javax.persistence.Entity` annotatio
|
||||||
The `@Entity` annotation defines just one attribute `name` which is used to give a specific entity name for use in JPQL queries.
|
The `@Entity` annotation defines just one attribute `name` which is used to give a specific entity name for use in JPQL queries.
|
||||||
By default, the entity name represents the unqualified name of the entity class itself.
|
By default, the entity name represents the unqualified name of the entity class itself.
|
||||||
|
|
||||||
.Simple `@Entity`
|
[[entity-pojo-mapping-example]]
|
||||||
|
.Simple `@Entity` mapping
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/SimpleEntity.java[]
|
include::{sourcedir-mapping}/identifier/SimpleEntityTest.java[tag=entity-pojo-mapping-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
@ -129,11 +131,12 @@ The identifier uniquely identifies each row in that table.
|
||||||
By default, the name of the table is assumed to be the same as the name of the entity.
|
By default, the name of the table is assumed to be the same as the name of the entity.
|
||||||
To explicitly give the name of the table or to specify other information about the table, we would use the `javax.persistence.Table` annotation.
|
To explicitly give the name of the table or to specify other information about the table, we would use the `javax.persistence.Table` annotation.
|
||||||
|
|
||||||
|
[[entity-pojo-table-mapping-example]]
|
||||||
.Simple `@Entity` with `@Table`
|
.Simple `@Entity` with `@Table`
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/SimpleEntityWithTable.java[]
|
include::{sourcedir-mapping}/identifier/SimpleEntityTableTest.java[tag=entity-pojo-table-mapping-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
@ -162,88 +165,109 @@ Hibernate, however, works hard to make sure that does not happen within a given
|
||||||
In fact, Hibernate guarantees equivalence of persistent identity (database row) and Java identity inside a particular session scope.
|
In fact, Hibernate guarantees equivalence of persistent identity (database row) and Java identity inside a particular session scope.
|
||||||
So if we ask a Hibernate `Session` to load that specific Person multiple times we will actually get back the same __instance__:
|
So if we ask a Hibernate `Session` to load that specific Person multiple times we will actually get back the same __instance__:
|
||||||
|
|
||||||
|
[[entity-pojo-identity-scope-example]]
|
||||||
.Scope of identity
|
.Scope of identity
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/listing1.java[]
|
include::{sourcedir-mapping}/identifier/SimpleEntityTest.java[tag=entity-pojo-identity-scope-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
Consider another example using a persistent `java.util.Set`:
|
Consider we have a `Library` parent entity which contains a `java.util.Set` of `Book` entities:
|
||||||
|
|
||||||
|
[[entity-pojo-set-mapping-example]]
|
||||||
|
Library entity mapping
|
||||||
|
====
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
include::{sourcedir-mapping}/identifier/SimpleEntityTest.java[tag=entity-pojo-set-mapping-example, indent=0]
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
[[entity-pojo-set-identity-scope-example]]
|
||||||
.Set usage with Session-scoped identity
|
.Set usage with Session-scoped identity
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/listing3.java[]
|
include::{sourcedir-mapping}/identifier/SimpleEntityTest.java[tag=entity-pojo-set-identity-scope-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
However, the semantic changes when we mix instances loaded from different Sessions:
|
However, the semantic changes when we mix instances loaded from different Sessions:
|
||||||
|
|
||||||
|
[[entity-pojo-multi-session-identity-scope-example]]
|
||||||
.Mixed Sessions
|
.Mixed Sessions
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/listing2.java[]
|
include::{sourcedir-mapping}/identifier/SimpleEntityTest.java[tag=entity-pojo-multi-session-identity-scope-example, indent=0]
|
||||||
----
|
----
|
||||||
|
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/listing4.java[]
|
include::{sourcedir-mapping}/identifier/SimpleEntityTest.java[tag=entity-pojo-multi-session-set-identity-scope-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
Specifically the outcome in this last example will depend on whether the `Person` class implemented equals/hashCode, and, if so, how.
|
Specifically the outcome in this last example will depend on whether the `Book` class
|
||||||
|
implemented equals/hashCode, and, if so, how.
|
||||||
|
|
||||||
|
If the `Book` class did not override the default equals/hashCode,
|
||||||
|
then the two `Book` object reference are not going to be equal since their references are different.
|
||||||
|
|
||||||
Consider yet another case:
|
Consider yet another case:
|
||||||
|
|
||||||
|
[[entity-pojo-transient-set-identity-scope-example]]
|
||||||
.Sets with transient entities
|
.Sets with transient entities
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/listing5.java[]
|
include::{sourcedir-mapping}/identifier/SimpleEntityTest.java[tag=entity-pojo-transient-set-identity-scope-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
In cases where you will be dealing with entities outside of a Session (whether they be transient or detached), especially in cases where you will be using them in Java collections,
|
In cases where you will be dealing with entities outside of a Session (whether they be transient or detached),
|
||||||
|
especially in cases where you will be using them in Java collections,
|
||||||
you should consider implementing equals/hashCode.
|
you should consider implementing equals/hashCode.
|
||||||
|
|
||||||
A common initial approach is to use the entity's identifier attribute as the basis for equals/hashCode calculations:
|
A common initial approach is to use the entity's identifier attribute as the basis for equals/hashCode calculations:
|
||||||
|
|
||||||
|
[[entity-pojo-naive-equals-hashcode-example]]
|
||||||
.Naive equals/hashCode implementation
|
.Naive equals/hashCode implementation
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/listing6.java[]
|
include::{sourcedir-mapping}/identifier/NaiveEqualsHashCodeEntityTest.java[tag=entity-pojo-naive-equals-hashcode-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
It turns out that this still breaks when adding transient instance of `Person` to a set as we saw in the last example:
|
It turns out that this still breaks when adding transient instance of `Book` to a set as we saw in the last example:
|
||||||
|
|
||||||
.Still trouble
|
[[entity-pojo-naive-equals-hashcode-example]]
|
||||||
|
.Auto-generated identifiers with Sets and naive equals/hashCode
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/listing7.java[]
|
include::{sourcedir-mapping}/identifier/NaiveEqualsHashCodeEntityTest.java[tag=entity-pojo-naive-equals-hashcode-persist-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
The issue here is a conflict between the use of generated identifier, the contract of `Set` and the equals/hashCode implementations.
|
The issue here is a conflict between the use of generated identifier, the contract of `Set` and the equals/hashCode implementations.
|
||||||
`Set` says that the equals/hashCode value for an object should not change while the object is part of the `Set`.
|
`Set` says that the equals/hashCode value for an object should not change while the object is part of the `Set`.
|
||||||
But that is exactly what happened here because the equals/hasCode are based on the (generated) id, which was not set until the `session.getTransaction().commit()` call.
|
But that is exactly what happened here because the equals/hasCode are based on the (generated) id, which was not set until the JPA transaction is committed.
|
||||||
|
|
||||||
Note that this is just a concern when using generated identifiers.
|
Note that this is just a concern when using generated identifiers.
|
||||||
If you are using assigned identifiers this will not be a problem, assuming the identifier value is assigned prior to adding to the `Set`.
|
If you are using assigned identifiers this will not be a problem, assuming the identifier value is assigned prior to adding to the `Set`.
|
||||||
|
|
||||||
Another option is to force the identifier to be generated and set prior to adding to the `Set`:
|
Another option is to force the identifier to be generated and set prior to adding to the `Set`:
|
||||||
|
|
||||||
.Forcing identifier generation
|
[[entity-pojo-naive-equals-hashcode-persist-force-flush-example]]
|
||||||
|
.Forcing the flush before adding to the Set
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/listing8.java[]
|
include::{sourcedir-mapping}/identifier/NaiveEqualsHashCodeEntityTest.java[tag=entity-pojo-naive-equals-hashcode-persist-force-flush-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
@ -251,11 +275,23 @@ But this is often not feasible.
|
||||||
|
|
||||||
The final approach is to use a "better" equals/hashCode implementation, making use of a natural-id or business-key.
|
The final approach is to use a "better" equals/hashCode implementation, making use of a natural-id or business-key.
|
||||||
|
|
||||||
.Better equals/hashCode with natural-id
|
[[entity-pojo-natural-id-equals-hashcode-example]]
|
||||||
|
.Natural Id equals/hashCode
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{extrasdir}/entity/listing9.java[]
|
include::{sourcedir-mapping}/identifier/NaturalIdEqualsHashCodeEntityTest.java[tag=entity-pojo-natural-id-equals-hashcode-example, indent=0]
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
This time, when adding a `Book` to the `Library` `Set`, you can retrieve the `Book` even after it's being persisted:
|
||||||
|
|
||||||
|
[[entity-pojo-natural-id-equals-hashcode-persist-example]]
|
||||||
|
.Natural Id equals/hashCode persist example
|
||||||
|
====
|
||||||
|
[source,java]
|
||||||
|
----
|
||||||
|
include::{sourcedir-mapping}/identifier/NaturalIdEqualsHashCodeEntityTest.java[tag=entity-pojo-natural-id-equals-hashcode-persist-example, indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
@ -283,7 +319,7 @@ You can map an entity to a SQL query using the https://docs.jboss.org/hibernate/
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{sourcedir-mapping}/SubselectTest.java[tag=mapping-Subselect-example,indent=0]
|
include::{sourcedir-mapping}/basic/SubselectTest.java[tag=mapping-Subselect-example,indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
@ -299,7 +335,7 @@ So, if we have the following `AccountTransaction` record, the `AccountSummary` b
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{sourcedir-mapping}/SubselectTest.java[tag=mapping-Subselect-entity-find-example,indent=0]
|
include::{sourcedir-mapping}/basic/SubselectTest.java[tag=mapping-Subselect-entity-find-example,indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
@ -310,7 +346,7 @@ If we add a new `AccountTransaction` entity and refresh the `AccountSummary` ent
|
||||||
====
|
====
|
||||||
[source,java]
|
[source,java]
|
||||||
----
|
----
|
||||||
include::{sourcedir-mapping}/SubselectTest.java[tag=mapping-Subselect-entity-refresh-example,indent=0]
|
include::{sourcedir-mapping}/basic/SubselectTest.java[tag=mapping-Subselect-entity-refresh-example,indent=0]
|
||||||
----
|
----
|
||||||
====
|
====
|
||||||
|
|
||||||
|
|
|
@ -1,2 +0,0 @@
|
||||||
@Id
|
|
||||||
private Integer id;
|
|
|
@ -1,4 +0,0 @@
|
||||||
@Entity
|
|
||||||
public class Simple {
|
|
||||||
...
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
@Entity
|
|
||||||
@Table( catalog = "CRM", schema = "purchasing", name = "t_simple" )
|
|
||||||
public class Simple {
|
|
||||||
...
|
|
||||||
}
|
|
|
@ -1,7 +0,0 @@
|
||||||
Session session=...;
|
|
||||||
|
|
||||||
Person p1 = session.get( Person.class,1 );
|
|
||||||
Person p2 = session.get( Person.class,1 );
|
|
||||||
|
|
||||||
// this evaluates to true
|
|
||||||
assert p1==p2;
|
|
|
@ -1,8 +0,0 @@
|
||||||
Session session1=...;
|
|
||||||
Session session2=...;
|
|
||||||
|
|
||||||
Person p1 = session1.get( Person.class,1 );
|
|
||||||
Person p2 = session2.get( Person.class,1 );
|
|
||||||
|
|
||||||
// this evaluates to false
|
|
||||||
assert p1==p2;
|
|
|
@ -1,12 +0,0 @@
|
||||||
Session session=...;
|
|
||||||
|
|
||||||
Club club = session.get( Club.class,1 );
|
|
||||||
|
|
||||||
Person p1 = session.get( Person.class,1 );
|
|
||||||
Person p2 = session.get( Person.class,1 );
|
|
||||||
|
|
||||||
club.getMembers().add( p1 );
|
|
||||||
club.getMembers().add( p2 );
|
|
||||||
|
|
||||||
// this evaluates to true
|
|
||||||
assert club.getMembers.size()==1;
|
|
|
@ -1,13 +0,0 @@
|
||||||
Session session1=...;
|
|
||||||
Session session2=...;
|
|
||||||
|
|
||||||
Club club = session1.get( Club.class,1 );
|
|
||||||
|
|
||||||
Person p1 = session1.get( Person.class,1 );
|
|
||||||
Person p2 = session2.get( Person.class,1 );
|
|
||||||
|
|
||||||
club.getMembers().add( p1 );
|
|
||||||
club.getMembers().add( p2 );
|
|
||||||
|
|
||||||
// this evaluates to ... well it depends
|
|
||||||
assert club.getMembers.size()==1;
|
|
|
@ -1,12 +0,0 @@
|
||||||
Session session=...;
|
|
||||||
|
|
||||||
Club club = session.get( Club.class,1 );
|
|
||||||
|
|
||||||
Person p1 = new Person(...);
|
|
||||||
Person p2 = new Person(...);
|
|
||||||
|
|
||||||
club.getMembers().add( p1 );
|
|
||||||
club.getMembers().add( p2 );
|
|
||||||
|
|
||||||
// this evaluates to ... again, it depends
|
|
||||||
assert club.getMembers.size()==1;
|
|
|
@ -1,24 +0,0 @@
|
||||||
@Entity
|
|
||||||
public class Person {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash( id );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if ( this == o ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ( !( o instanceof Person ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Person person = (Person) o;
|
|
||||||
return Objects.equals( id, person.id );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
Session session=...;
|
|
||||||
session.getTransaction().begin();
|
|
||||||
|
|
||||||
Club club = session.get( Club.class,1 );
|
|
||||||
|
|
||||||
Person p1 = new Person(...);
|
|
||||||
Person p2 = new Person(...);
|
|
||||||
|
|
||||||
club.getMembers().add( p1 );
|
|
||||||
club.getMembers().add( p2 );
|
|
||||||
|
|
||||||
session.getTransaction().commit();
|
|
||||||
|
|
||||||
// will actually resolve to false!
|
|
||||||
assert club.getMembers().contains( p1 );
|
|
|
@ -1,19 +0,0 @@
|
||||||
Session session=...;
|
|
||||||
session.getTransaction().begin();
|
|
||||||
|
|
||||||
Club club = session.get( Club.class,1 );
|
|
||||||
|
|
||||||
Person p1 = new Person(...);
|
|
||||||
Person p2 = new Person(...);
|
|
||||||
|
|
||||||
session.save( p1 );
|
|
||||||
session.save( p2 );
|
|
||||||
session.flush();
|
|
||||||
|
|
||||||
club.getMembers().add( p1 );
|
|
||||||
club.getMembers().add( p2 );
|
|
||||||
|
|
||||||
session.getTransaction().commit();
|
|
||||||
|
|
||||||
// will actually resolve to false!
|
|
||||||
assert club.getMembers().contains( p1 );
|
|
|
@ -1,36 +0,0 @@
|
||||||
@Entity
|
|
||||||
public class Person {
|
|
||||||
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
private Integer id;
|
|
||||||
|
|
||||||
@NaturalId
|
|
||||||
private String ssn;
|
|
||||||
|
|
||||||
protected Person() {
|
|
||||||
// Constructor for ORM
|
|
||||||
}
|
|
||||||
|
|
||||||
public Person( String ssn ) {
|
|
||||||
// Constructor for app
|
|
||||||
this.ssn = ssn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return Objects.hash( ssn );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if ( this == o ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if ( !( o instanceof Person ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Person person = (Person) o;
|
|
||||||
return Objects.equals( ssn, person.ssn );
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,201 @@
|
||||||
|
/*
|
||||||
|
* 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.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class NaiveEqualsHashCodeEntityTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Library.class,
|
||||||
|
Book.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Library library = new Library();
|
||||||
|
library.setId( 1L );
|
||||||
|
library.setName( "Amazon" );
|
||||||
|
|
||||||
|
entityManager.persist( library );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPersist() {
|
||||||
|
|
||||||
|
//tag::entity-pojo-naive-equals-hashcode-persist-example[]
|
||||||
|
Book book1 = new Book();
|
||||||
|
book1.setTitle( "High-Performance Java Persistence" );
|
||||||
|
|
||||||
|
Book book2 = new Book();
|
||||||
|
book2.setTitle( "Java Persistence with Hibernate" );
|
||||||
|
|
||||||
|
Library library = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Library _library = entityManager.find( Library.class, 1L );
|
||||||
|
|
||||||
|
_library.getBooks().add( book1 );
|
||||||
|
_library.getBooks().add( book2 );
|
||||||
|
|
||||||
|
return _library;
|
||||||
|
} );
|
||||||
|
|
||||||
|
assertFalse( library.getBooks().contains( book1 ) );
|
||||||
|
assertFalse( library.getBooks().contains( book2 ) );
|
||||||
|
//end::entity-pojo-naive-equals-hashcode-persist-example[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPersistForceFlush() {
|
||||||
|
|
||||||
|
//tag::entity-pojo-naive-equals-hashcode-persist-force-flush-example[]
|
||||||
|
Book book1 = new Book();
|
||||||
|
book1.setTitle( "High-Performance Java Persistence" );
|
||||||
|
|
||||||
|
Book book2 = new Book();
|
||||||
|
book2.setTitle( "Java Persistence with Hibernate" );
|
||||||
|
|
||||||
|
Library library = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Library _library = entityManager.find( Library.class, 1L );
|
||||||
|
|
||||||
|
entityManager.persist( book1 );
|
||||||
|
entityManager.persist( book2 );
|
||||||
|
entityManager.flush();
|
||||||
|
|
||||||
|
_library.getBooks().add( book1 );
|
||||||
|
_library.getBooks().add( book2 );
|
||||||
|
|
||||||
|
return _library;
|
||||||
|
} );
|
||||||
|
|
||||||
|
assertTrue( library.getBooks().contains( book1 ) );
|
||||||
|
assertTrue( library.getBooks().contains( book2 ) );
|
||||||
|
//end::entity-pojo-naive-equals-hashcode-persist-force-flush-example[]
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::entity-pojo-naive-equals-hashcode-example[]
|
||||||
|
@Entity(name = "Library")
|
||||||
|
public static class Library {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL)
|
||||||
|
@JoinColumn(name = "book_id")
|
||||||
|
private Set<Book> books = new HashSet<>();
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::entity-pojo-naive-equals-hashcode-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 Set<Book> getBooks() {
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
//tag::entity-pojo-naive-equals-hashcode-example[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Book")
|
||||||
|
public static class Book {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::entity-pojo-naive-equals-hashcode-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;
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::entity-pojo-naive-equals-hashcode-example[]
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( o == null || getClass() != o.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Book book = (Book) o;
|
||||||
|
return Objects.equals( id, book.id );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash( id );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//end::entity-pojo-naive-equals-hashcode-example[]
|
||||||
|
}
|
|
@ -0,0 +1,180 @@
|
||||||
|
/*
|
||||||
|
* 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.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.NaturalId;
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class NaturalIdEqualsHashCodeEntityTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Library.class,
|
||||||
|
Book.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Library library = new Library();
|
||||||
|
library.setId( 1L );
|
||||||
|
library.setName( "Amazon" );
|
||||||
|
|
||||||
|
entityManager.persist( library );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPersist() {
|
||||||
|
|
||||||
|
//tag::entity-pojo-natural-id-equals-hashcode-persist-example[]
|
||||||
|
Book book1 = new Book();
|
||||||
|
book1.setTitle( "High-Performance Java Persistence" );
|
||||||
|
book1.setIsbn( "978-9730228236" );
|
||||||
|
|
||||||
|
Library library = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Library _library = entityManager.find( Library.class, 1L );
|
||||||
|
|
||||||
|
_library.getBooks().add( book1 );
|
||||||
|
|
||||||
|
return _library;
|
||||||
|
} );
|
||||||
|
|
||||||
|
assertTrue( library.getBooks().contains( book1 ) );
|
||||||
|
//end::entity-pojo-natural-id-equals-hashcode-persist-example[]
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::entity-pojo-natural-id-equals-hashcode-example[]
|
||||||
|
@Entity(name = "Library")
|
||||||
|
public static class Library {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL)
|
||||||
|
@JoinColumn(name = "book_id")
|
||||||
|
private Set<Book> books = new HashSet<>();
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::entity-pojo-natural-id-equals-hashcode-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 Set<Book> getBooks() {
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
//tag::entity-pojo-natural-id-equals-hashcode-example[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity(name = "Book")
|
||||||
|
public static class Book {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
@NaturalId
|
||||||
|
private String isbn;
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::entity-pojo-natural-id-equals-hashcode-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::entity-pojo-natural-id-equals-hashcode-example[]
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if ( this == o ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if ( o == null || getClass() != o.getClass() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Book book = (Book) o;
|
||||||
|
return Objects.equals( isbn, book.isbn );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash( isbn );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//end::entity-pojo-natural-id-equals-hashcode-example[]
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* 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 javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class SimpleEntityTableTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Book.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::entity-pojo-table-mapping-example[]
|
||||||
|
@Entity(name = "Book")
|
||||||
|
@Table(
|
||||||
|
catalog = "public",
|
||||||
|
schema = "store",
|
||||||
|
name = "book"
|
||||||
|
)
|
||||||
|
public static class Book {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::entity-pojo-table-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;
|
||||||
|
}
|
||||||
|
//tag::entity-pojo-table-mapping-example[]
|
||||||
|
}
|
||||||
|
//end::entity-pojo-table-mapping-example[]
|
||||||
|
}
|
|
@ -0,0 +1,236 @@
|
||||||
|
/*
|
||||||
|
* 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.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Vlad Mihalcea
|
||||||
|
*/
|
||||||
|
public class SimpleEntityTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Class<?>[] getAnnotatedClasses() {
|
||||||
|
return new Class<?>[] {
|
||||||
|
Library.class,
|
||||||
|
Book.class
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void init() {
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Library library = new Library();
|
||||||
|
library.setId( 1L );
|
||||||
|
library.setName( "Amazon" );
|
||||||
|
|
||||||
|
entityManager.persist( library );
|
||||||
|
|
||||||
|
Book book = new Book();
|
||||||
|
book.setId( 1L );
|
||||||
|
book.setTitle( "High-Performance Java Persistence" );
|
||||||
|
book.setAuthor( "Vlad Mihalcea" );
|
||||||
|
|
||||||
|
entityManager.persist( book );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testIdentityScope() {
|
||||||
|
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
//tag::entity-pojo-identity-scope-example[]
|
||||||
|
Book book1 = entityManager.find( Book.class, 1L );
|
||||||
|
Book book2 = entityManager.find( Book.class, 1L );
|
||||||
|
|
||||||
|
assertTrue( book1 == book2 );
|
||||||
|
//end::entity-pojo-identity-scope-example[]
|
||||||
|
} );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSetIdentityScope() {
|
||||||
|
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
//tag::entity-pojo-set-identity-scope-example[]
|
||||||
|
Library library = entityManager.find( Library.class, 1L );
|
||||||
|
|
||||||
|
Book book1 = entityManager.find( Book.class, 1L );
|
||||||
|
Book book2 = entityManager.find( Book.class, 1L );
|
||||||
|
|
||||||
|
library.getBooks().add( book1 );
|
||||||
|
library.getBooks().add( book2 );
|
||||||
|
|
||||||
|
assertEquals( 1, library.getBooks().size() );
|
||||||
|
//end::entity-pojo-set-identity-scope-example[]
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiSessionIdentityScope() {
|
||||||
|
|
||||||
|
//tag::entity-pojo-multi-session-identity-scope-example[]
|
||||||
|
Book book1 = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
return entityManager.find( Book.class, 1L );
|
||||||
|
} );
|
||||||
|
|
||||||
|
Book book2 = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
return entityManager.find( Book.class, 1L );
|
||||||
|
} );
|
||||||
|
|
||||||
|
assertFalse( book1 == book2 );
|
||||||
|
//end::entity-pojo-multi-session-identity-scope-example[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultiSessionSetIdentityScope() {
|
||||||
|
|
||||||
|
Book book1 = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
return entityManager.find( Book.class, 1L );
|
||||||
|
} );
|
||||||
|
|
||||||
|
Book book2 = doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
return entityManager.find( Book.class, 1L );
|
||||||
|
} );
|
||||||
|
//tag::entity-pojo-multi-session-set-identity-scope-example[]
|
||||||
|
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
Set<Book> books = new HashSet<>();
|
||||||
|
|
||||||
|
books.add( book1 );
|
||||||
|
books.add( book2 );
|
||||||
|
|
||||||
|
assertEquals( 2, books.size() );
|
||||||
|
} );
|
||||||
|
//end::entity-pojo-multi-session-set-identity-scope-example[]
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTransientSetIdentityScope() {
|
||||||
|
|
||||||
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
//tag::entity-pojo-transient-set-identity-scope-example[]
|
||||||
|
Library library = entityManager.find( Library.class, 1L );
|
||||||
|
|
||||||
|
Book book1 = new Book();
|
||||||
|
book1.setId( 100L );
|
||||||
|
book1.setTitle( "High-Performance Java Persistence" );
|
||||||
|
|
||||||
|
Book book2 = new Book();
|
||||||
|
book2.setId( 101L );
|
||||||
|
book2.setTitle( "Java Persistence with Hibernate" );
|
||||||
|
|
||||||
|
library.getBooks().add( book1 );
|
||||||
|
library.getBooks().add( book2 );
|
||||||
|
|
||||||
|
assertEquals( 2, library.getBooks().size() );
|
||||||
|
//end::entity-pojo-transient-set-identity-scope-example[]
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::entity-pojo-set-mapping-example[]
|
||||||
|
@Entity(name = "Library")
|
||||||
|
public static class Library {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL)
|
||||||
|
@JoinColumn(name = "book_id")
|
||||||
|
private Set<Book> books = new HashSet<>();
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::entity-pojo-set-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 Set<Book> getBooks() {
|
||||||
|
return books;
|
||||||
|
}
|
||||||
|
//tag::entity-pojo-set-mapping-example[]
|
||||||
|
}
|
||||||
|
//end::entity-pojo-set-mapping-example[]
|
||||||
|
|
||||||
|
//tag::entity-pojo-mapping-example[]
|
||||||
|
@Entity(name = "Book")
|
||||||
|
public static class Book {
|
||||||
|
|
||||||
|
//tag::entity-pojo-identifier-mapping-example[]
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
//end::entity-pojo-identifier-mapping-example[]
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
//Getters and setters are omitted for brevity
|
||||||
|
//end::entity-pojo-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;
|
||||||
|
}
|
||||||
|
//tag::entity-pojo-mapping-example[]
|
||||||
|
}
|
||||||
|
//end::entity-pojo-mapping-example[]
|
||||||
|
}
|
Loading…
Reference in New Issue