HHH-11290 - Migrate all documentation snippets that derive the source code from extras instead of actual Unit Tests
Fixed in the Embeddable chapter
This commit is contained in:
parent
c39a337418
commit
c42df6a11b
|
@ -6,7 +6,9 @@
|
|||
Historically Hibernate called these components.
|
||||
JPA calls them embeddables.
|
||||
Either way the concept is the same: a composition of values.
|
||||
For example we might have a Name class that is a composition of first-name and last-name, or an Address class that is a composition of street, city, postal code, etc.
|
||||
|
||||
For example we might have a `Publisher` class that is a composition of `name` and `country`,
|
||||
or a `Location` class that is a composition of `country` and `city`.
|
||||
|
||||
.Usage of the word _embeddable_
|
||||
[NOTE]
|
||||
|
@ -16,16 +18,12 @@ To avoid any confusion with the annotation that marks a given embeddable type, t
|
|||
Throughout this chapter and thereafter, for brevity sake, embeddable types may also be referred as _embeddable_.
|
||||
====
|
||||
|
||||
.Simple embeddable type example
|
||||
[[embeddable-type-mapping-example]]
|
||||
.Embeddable type example
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{extrasdir}/embeddable/Name.java[]
|
||||
----
|
||||
|
||||
[source,java]
|
||||
----
|
||||
include::{extrasdir}/embeddable/Address.java[]
|
||||
include::{sourcedir}/NestedEmbeddableTest.java[tag=embeddable-type-mapping-example, indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
|
@ -37,40 +35,42 @@ Embeddable types can be made up of basic values as well as associations, with th
|
|||
|
||||
Most often, embeddable types are used to group multiple basic type mappings and reuse them across several entities.
|
||||
|
||||
[[simple-embeddable-type-mapping-example]]
|
||||
.Simple Embeddedable
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{extrasdir}/embeddable/Person.java[]
|
||||
include::{sourcedir}/SimpleEmbeddableTest.java[tag=embeddable-type-mapping-example, indent=0]
|
||||
----
|
||||
|
||||
[source,sql]
|
||||
----
|
||||
include::{extrasdir}/embeddable/simple-embeddable-type-mapping-example.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
JPA defines two terms for working with an embeddable type: `@Embeddable` and `@Embedded`.
|
||||
`@Embeddable` is used to describe the mapping type itself (e.g. `Name`).
|
||||
`@Embedded` is for referencing a given embeddable type (e.g. `person.name`).
|
||||
|
||||
`@Embeddable` is used to describe the mapping type itself (e.g. `Publisher`).
|
||||
|
||||
`@Embedded` is for referencing a given embeddable type (e.g. `book#publisher`).
|
||||
====
|
||||
|
||||
So, the embeddable type is represented by the `Name` class and the parent makes use of it through the `person.name` object composition.
|
||||
|
||||
.Person table
|
||||
====
|
||||
[source,sql]
|
||||
----
|
||||
include::{extrasdir}/embeddable/Person1.sql[]
|
||||
----
|
||||
====
|
||||
So, the embeddable type is represented by the `Publisher` class and
|
||||
the parent entity makes use of it through the `book#publisher` object composition.
|
||||
|
||||
The composed values are mapped to the same table as the parent table.
|
||||
Composition is part of good OO data modeling (idiomatic Java).
|
||||
Composition is part of good Object-oriented data modeling (idiomatic Java).
|
||||
In fact, that table could also be mapped by the following entity type instead.
|
||||
|
||||
[[alternative-to-embeddable-type-mapping-example]]
|
||||
.Alternative to embeddable type composition
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{extrasdir}/embeddable/Person_alt.java[]
|
||||
include::{sourcedir}/SimpleEmbeddableEquivalentTest.java[tag=embeddable-type-mapping-example, indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
|
@ -79,14 +79,6 @@ The composition form is certainly more Object-oriented, and that becomes more ev
|
|||
[[embeddable-multiple]]
|
||||
==== Multiple embeddable types
|
||||
|
||||
.Multiple embeddable types
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{extrasdir}/embeddable/Contact.java[]
|
||||
----
|
||||
====
|
||||
|
||||
Although from an object-oriented perspective, it's much more convenient to work with embeddable types, this example doesn't work as-is.
|
||||
When the same embeddable type is included multiple times in the same parent entity type, the JPA specification demands setting the associated column names explicitly.
|
||||
|
||||
|
@ -96,77 +88,12 @@ When including multiple embeddables, the implicit name-based mapping rule doesn'
|
|||
|
||||
We have a few options to handle this issue.
|
||||
|
||||
[[embeddable-multiple-jpa]]
|
||||
==== JPA's AttributeOverride
|
||||
|
||||
JPA defines the `@AttributeOverride` annotation to handle this scenario.
|
||||
|
||||
.JPA's AttributeOverride
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{extrasdir}/embeddable/Contact-AttributeOverride.java[]
|
||||
----
|
||||
====
|
||||
|
||||
This way, the mapping conflict is resolved by setting up explicit name-based property-column type mappings.
|
||||
|
||||
[[embeddable-multiple-namingstrategy]]
|
||||
==== Embeddables and ImplicitNamingStrategy
|
||||
|
||||
[IMPORTANT]
|
||||
====
|
||||
This is a Hibernate specific feature.
|
||||
Users concerned with JPA provider portability should instead prefer explicit column naming with <<embeddable-multiple-jpa,`@AttributeOverride`>>.
|
||||
====
|
||||
|
||||
Hibernate naming strategies are covered in detail in <<chapters/domain/naming.adoc#naming,Naming>>.
|
||||
However, for the purposes of this discussion, Hibernate has the capability to interpret implicit column names in a way that is safe for use with multiple embeddable types.
|
||||
|
||||
.Enabling embeddable type safe implicit naming
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{extrasdir}/embeddable/component-safe-implicit-naming.java[]
|
||||
----
|
||||
====
|
||||
|
||||
====
|
||||
[source,sql]
|
||||
----
|
||||
include::{extrasdir}/embeddable/Contact-ImplicitNamingStrategy.sql[]
|
||||
----
|
||||
====
|
||||
|
||||
Now the "path" to attributes are used in the implicit column naming.
|
||||
You could even develop your own to do special implicit naming.
|
||||
|
||||
[[embeddable-collections]]
|
||||
==== Collections of embeddable types
|
||||
|
||||
Collections of embeddable types are specifically value collections (as embeddable types are a value type).
|
||||
Value collections are covered in detail in <<chapters/domain/collections.adoc#collections-value,Collections of value types>>.
|
||||
|
||||
[[embeddable-mapkey]]
|
||||
==== Embeddable types as Map key
|
||||
|
||||
Embeddable types can also be used as `Map` keys.
|
||||
This topic is converted in detail in <<chapters/domain/collections.adoc#collections-map,Map - key>>.
|
||||
|
||||
[[embeddable-identifier]]
|
||||
==== Embeddable types as identifiers
|
||||
|
||||
Embeddable types can also be used as entity type identifiers.
|
||||
This usage is covered in detail in <<chapters/domain/identifiers.adoc#identifiers-composite,Composite identifiers>>.
|
||||
|
||||
[IMPORTANT]
|
||||
====
|
||||
Embeddable types that are used as collection entries, map keys or entity type identifiers cannot include their own collection mappings.
|
||||
====
|
||||
|
||||
[[embeddable-override]]
|
||||
==== Overriding Embeddable types
|
||||
|
||||
JPA defines the `@AttributeOverride` annotation to handle this scenario.
|
||||
This way, the mapping conflict is resolved by setting up explicit name-based property-column type mappings.
|
||||
|
||||
If an Embeddabe type is used multiple times in some entity, you need to use the
|
||||
http://docs.oracle.com/javaee/7/api/javax/persistence/AttributeOverride.html[`@AttributeOverride`] and
|
||||
http://docs.oracle.com/javaee/7/api/javax/persistence/AssociationOverride.html[`@AssociationOverride`] annotations
|
||||
|
@ -208,4 +135,66 @@ include::{extrasdir}/embeddable/embeddable-type-override-mapping-example.sql[]
|
|||
----
|
||||
====
|
||||
|
||||
[[embeddable-multiple-namingstrategy]]
|
||||
==== Embeddables and ImplicitNamingStrategy
|
||||
|
||||
[IMPORTANT]
|
||||
====
|
||||
This is a Hibernate specific feature.
|
||||
Users concerned with JPA provider portability should instead prefer explicit column naming with `@AttributeOverride`.
|
||||
====
|
||||
|
||||
Hibernate naming strategies are covered in detail in <<chapters/domain/naming.adoc#naming,Naming>>.
|
||||
However, for the purposes of this discussion, Hibernate has the capability to interpret implicit column names in a way that is safe for use with multiple embeddable types.
|
||||
|
||||
[[embeddable-multiple-namingstrategy-entity-mapping]]
|
||||
.Implicit multiple embeddable type mapping
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{sourcedir}/EmbeddableImplicitOverrideTest.java[tag=embeddable-multiple-namingstrategy-entity-mapping, indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
To make it work, you need to use the `ImplicitNamingStrategyComponentPathImpl` naming strategy.
|
||||
|
||||
[[embeddable-multiple-ImplicitNamingStrategyComponentPathImpl]]
|
||||
.Enabling implicit embeddable type mapping using the component path naming strategy
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
include::{sourcedir}/EmbeddableImplicitOverrideTest.java[tag=embeddable-multiple-ImplicitNamingStrategyComponentPathImpl, indent=0]
|
||||
----
|
||||
====
|
||||
|
||||
Now the "path" to attributes are used in the implicit column naming:
|
||||
|
||||
[source,sql]
|
||||
----
|
||||
include::{extrasdir}/embeddable/embeddable-multiple-namingstrategy-entity-mapping.sql[]
|
||||
----
|
||||
|
||||
You could even develop your own naming strategy to do other types of implicit naming strategies.
|
||||
|
||||
[[embeddable-collections]]
|
||||
==== Collections of embeddable types
|
||||
|
||||
Collections of embeddable types are specifically value collections (as embeddable types are a value type).
|
||||
Value collections are covered in detail in <<chapters/domain/collections.adoc#collections-value,Collections of value types>>.
|
||||
|
||||
[[embeddable-mapkey]]
|
||||
==== Embeddable types as Map key
|
||||
|
||||
Embeddable types can also be used as `Map` keys.
|
||||
This topic is converted in detail in <<chapters/domain/collections.adoc#collections-map,Map - key>>.
|
||||
|
||||
[[embeddable-identifier]]
|
||||
==== Embeddable types as identifiers
|
||||
|
||||
Embeddable types can also be used as entity type identifiers.
|
||||
This usage is covered in detail in <<chapters/domain/identifiers.adoc#identifiers-composite,Composite identifiers>>.
|
||||
|
||||
[IMPORTANT]
|
||||
====
|
||||
Embeddable types that are used as collection entries, map keys or entity type identifiers cannot include their own collection mappings.
|
||||
====
|
|
@ -1,22 +0,0 @@
|
|||
@Embeddable
|
||||
public class Address {
|
||||
|
||||
private String line1;
|
||||
|
||||
private String line2;
|
||||
|
||||
@Embedded
|
||||
private ZipCode zipCode;
|
||||
|
||||
...
|
||||
|
||||
@Embeddable
|
||||
public static class ZipCode {
|
||||
|
||||
private String postalCode;
|
||||
|
||||
private String plus4;
|
||||
|
||||
...
|
||||
}
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
@Entity
|
||||
public class Contact {
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
@Embedded
|
||||
private Name name;
|
||||
|
||||
@Embedded
|
||||
@AttributeOverrides(
|
||||
@AttributeOverride(
|
||||
name = "line1",
|
||||
column = @Column( name = "home_address_line1" ),
|
||||
),
|
||||
@AttributeOverride(
|
||||
name = "line2",
|
||||
column = @Column( name = "home_address_line2" )
|
||||
),
|
||||
@AttributeOverride(
|
||||
name = "zipCode.postalCode",
|
||||
column = @Column( name = "home_address_postal_cd" )
|
||||
),
|
||||
@AttributeOverride(
|
||||
name = "zipCode.plus4",
|
||||
column = @Column( name = "home_address_postal_plus4" )
|
||||
)
|
||||
)
|
||||
private Address homeAddress;
|
||||
|
||||
@Embedded
|
||||
@AttributeOverrides(
|
||||
@AttributeOverride(
|
||||
name = "line1",
|
||||
column = @Column( name = "mailing_address_line1" ),
|
||||
),
|
||||
@AttributeOverride(
|
||||
name = "line2",
|
||||
column = @Column( name = "mailing_address_line2" )
|
||||
),
|
||||
@AttributeOverride(
|
||||
name = "zipCode.postalCode",
|
||||
column = @Column( name = "mailing_address_postal_cd" )
|
||||
),
|
||||
@AttributeOverride(
|
||||
name = "zipCode.plus4",
|
||||
column = @Column( name = "mailing_address_postal_plus4" )
|
||||
)
|
||||
)
|
||||
private Address mailingAddress;
|
||||
|
||||
@Embedded
|
||||
@AttributeOverrides(
|
||||
@AttributeOverride(
|
||||
name = "line1",
|
||||
column = @Column( name = "work_address_line1" ),
|
||||
),
|
||||
@AttributeOverride(
|
||||
name = "line2",
|
||||
column = @Column( name = "work_address_line2" )
|
||||
),
|
||||
@AttributeOverride(
|
||||
name = "zipCode.postalCode",
|
||||
column = @Column( name = "work_address_postal_cd" )
|
||||
),
|
||||
@AttributeOverride(
|
||||
name = "zipCode.plus4",
|
||||
column = @Column( name = "work_address_postal_plus4" )
|
||||
)
|
||||
)
|
||||
private Address workAddress;
|
||||
|
||||
...
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
create table Contact(
|
||||
id integer not null,
|
||||
name_firstName VARCHAR,
|
||||
name_middleName VARCHAR,
|
||||
name_lastName VARCHAR,
|
||||
homeAddress_line1 VARCHAR,
|
||||
homeAddress_line2 VARCHAR,
|
||||
homeAddress_zipCode_postalCode VARCHAR,
|
||||
homeAddress_zipCode_plus4 VARCHAR,
|
||||
mailingAddress_line1 VARCHAR,
|
||||
mailingAddress_line2 VARCHAR,
|
||||
mailingAddress_zipCode_postalCode VARCHAR,
|
||||
mailingAddress_zipCode_plus4 VARCHAR,
|
||||
workAddress_line1 VARCHAR,
|
||||
workAddress_line2 VARCHAR,
|
||||
workAddress_zipCode_postalCode VARCHAR,
|
||||
workAddress_zipCode_plus4 VARCHAR,
|
||||
...
|
||||
)
|
|
@ -1,20 +0,0 @@
|
|||
@Entity
|
||||
public class Contact {
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
@Embedded
|
||||
private Name name;
|
||||
|
||||
@Embedded
|
||||
private Address homeAddress;
|
||||
|
||||
@Embedded
|
||||
private Address mailingAddress;
|
||||
|
||||
@Embedded
|
||||
private Address workAddress;
|
||||
|
||||
...
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
@Embeddable
|
||||
public class Name {
|
||||
|
||||
private String firstName;
|
||||
|
||||
private String middleName;
|
||||
|
||||
private String lastName;
|
||||
|
||||
...
|
||||
}
|
|
@ -1,11 +0,0 @@
|
|||
@Entity
|
||||
public class Person {
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
@Embedded
|
||||
private Name name;
|
||||
|
||||
...
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
create table Person (
|
||||
id integer not null,
|
||||
firstName VARCHAR,
|
||||
middleName VARCHAR,
|
||||
lastName VARCHAR,
|
||||
...
|
||||
)
|
|
@ -1,14 +0,0 @@
|
|||
@Entity
|
||||
public class Person {
|
||||
|
||||
@Id
|
||||
private Integer id;
|
||||
|
||||
private String firstName;
|
||||
|
||||
private String middleName;
|
||||
|
||||
private String lastName;
|
||||
|
||||
...
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
MetadataSources sources = ...;
|
||||
sources.addAnnotatedClass( Address.class );
|
||||
sources.addAnnotatedClass( Name.class );
|
||||
sources.addAnnotatedClass( Contact.class );
|
||||
|
||||
Metadata metadata = sources.getMetadataBuilder().applyImplicitNamingStrategy( ImplicitNamingStrategyComponentPathImpl.INSTANCE )
|
||||
...
|
||||
.build();
|
|
@ -0,0 +1,10 @@
|
|||
create table Book (
|
||||
id bigint not null,
|
||||
author varchar(255),
|
||||
ebookPublisher_name varchar(255),
|
||||
paperBackPublisher_name varchar(255),
|
||||
title varchar(255),
|
||||
ebookPublisher_country_id bigint,
|
||||
paperBackPublisher_country_id bigint,
|
||||
primary key (id)
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
create table Book (
|
||||
id bigint not null,
|
||||
author varchar(255),
|
||||
publisher_country varchar(255),
|
||||
publisher_name varchar(255),
|
||||
title varchar(255),
|
||||
primary key (id)
|
||||
)
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* 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.embeddable;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.hibernate.annotations.NaturalId;
|
||||
import org.hibernate.boot.MetadataBuilder;
|
||||
import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
public class EmbeddableImplicitOverrideTest
|
||||
extends BaseNonConfigCoreFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Book.class,
|
||||
Country.class
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize(MetadataBuilder metadataBuilder) {
|
||||
super.initialize( metadataBuilder );
|
||||
//tag::embeddable-multiple-ImplicitNamingStrategyComponentPathImpl[]
|
||||
metadataBuilder.applyImplicitNamingStrategy(
|
||||
ImplicitNamingStrategyComponentPathImpl.INSTANCE
|
||||
);
|
||||
//end::embeddable-multiple-ImplicitNamingStrategyComponentPathImpl[]
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Country canada = new Country();
|
||||
canada.setName( "Canada" );
|
||||
session.persist( canada );
|
||||
|
||||
Country usa = new Country();
|
||||
usa.setName( "USA" );
|
||||
session.persist( usa );
|
||||
} );
|
||||
|
||||
doInHibernate( this::sessionFactory, session -> {
|
||||
Country canada = session.byNaturalId( Country.class ).using( "name", "Canada" ).load();
|
||||
Country usa = session.byNaturalId( Country.class ).using( "name", "USA" ).load();
|
||||
|
||||
Book book = new Book();
|
||||
book.setTitle( "High-Performance Java Persistence" );
|
||||
book.setAuthor( "Vlad Mihalcea" );
|
||||
book.setEbookPublisher( new Publisher( "Leanpub", canada ) );
|
||||
book.setPaperBackPublisher( new Publisher( "Amazon", usa ) );
|
||||
|
||||
session.persist( book );
|
||||
} );
|
||||
}
|
||||
|
||||
//tag::embeddable-multiple-namingstrategy-entity-mapping[]
|
||||
@Entity(name = "Book")
|
||||
public static class Book {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String author;
|
||||
|
||||
private Publisher ebookPublisher;
|
||||
|
||||
private Publisher paperBackPublisher;
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
//end::embeddable-multiple-namingstrategy-entity-mapping[]
|
||||
|
||||
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 Publisher getEbookPublisher() {
|
||||
return ebookPublisher;
|
||||
}
|
||||
|
||||
public void setEbookPublisher(Publisher ebookPublisher) {
|
||||
this.ebookPublisher = ebookPublisher;
|
||||
}
|
||||
|
||||
public Publisher getPaperBackPublisher() {
|
||||
return paperBackPublisher;
|
||||
}
|
||||
|
||||
public void setPaperBackPublisher(Publisher paperBackPublisher) {
|
||||
this.paperBackPublisher = paperBackPublisher;
|
||||
}
|
||||
//tag::embeddable-multiple-namingstrategy-entity-mapping[]
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class Publisher {
|
||||
|
||||
private String name;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
private Country country;
|
||||
|
||||
public Publisher(String name, Country country) {
|
||||
this.name = name;
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
private Publisher() {}
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
//end::embeddable-multiple-namingstrategy-entity-mapping[]
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Country getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(Country country) {
|
||||
this.country = country;
|
||||
}
|
||||
//tag::embeddable-multiple-namingstrategy-entity-mapping[]
|
||||
}
|
||||
|
||||
@Entity(name = "Country")
|
||||
public static class Country {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
@NaturalId
|
||||
private String name;
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
//end::embeddable-multiple-namingstrategy-entity-mapping[]
|
||||
|
||||
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::embeddable-multiple-namingstrategy-entity-mapping[]
|
||||
}
|
||||
//end::embeddable-multiple-namingstrategy-entity-mapping[]
|
||||
}
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* 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.embeddable;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
public class NestedEmbeddableTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Book.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
Book book = new Book();
|
||||
book.setTitle( "High-Performance Java Persistence" );
|
||||
book.setAuthor( "Vlad Mihalcea" );
|
||||
book.setPublisher(
|
||||
new Publisher(
|
||||
"Amazon",
|
||||
new Location(
|
||||
"USA",
|
||||
"Seattle"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
entityManager.persist( book );
|
||||
} );
|
||||
}
|
||||
|
||||
@Entity(name = "Book")
|
||||
public static class Book {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String author;
|
||||
|
||||
private Publisher publisher;
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
|
||||
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 Publisher getPublisher() {
|
||||
return publisher;
|
||||
}
|
||||
|
||||
public void setPublisher(Publisher publisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//tag::embeddable-type-mapping-example[]
|
||||
@Embeddable
|
||||
public static class Publisher {
|
||||
|
||||
private String name;
|
||||
|
||||
private Location location;
|
||||
|
||||
public Publisher(String name, Location location) {
|
||||
this.name = name;
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
private Publisher() {}
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
//end::embeddable-type-mapping-example[]
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Location getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public void setLocation(Location location) {
|
||||
this.location = location;
|
||||
}
|
||||
|
||||
//tag::embeddable-type-mapping-example[]
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class Location {
|
||||
|
||||
private String country;
|
||||
|
||||
private String city;
|
||||
|
||||
public Location(String country, String city) {
|
||||
this.country = country;
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
private Location() {}
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
//end::embeddable-type-mapping-example[]
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
//tag::embeddable-type-mapping-example[]
|
||||
}
|
||||
//end::embeddable-type-mapping-example[]
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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.embeddable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
public class SimpleEmbeddableEquivalentTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Book.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
Book book = new Book();
|
||||
book.setTitle( "High-Performance Java Persistence" );
|
||||
book.setAuthor( "Vlad Mihalcea" );
|
||||
book.setPublisherName("Amazon");
|
||||
book.setPublisherCountry("USA");
|
||||
|
||||
entityManager.persist( book );
|
||||
} );
|
||||
}
|
||||
|
||||
//tag::embeddable-type-mapping-example[]
|
||||
@Entity(name = "Book")
|
||||
public static class Book {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String author;
|
||||
|
||||
@Column(name = "publisher_name")
|
||||
private String publisherName;
|
||||
|
||||
@Column(name = "publisher_country")
|
||||
private String publisherCountry;
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
//end::embeddable-type-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 getPublisherName() {
|
||||
return publisherName;
|
||||
}
|
||||
|
||||
public void setPublisherName(String publisherName) {
|
||||
this.publisherName = publisherName;
|
||||
}
|
||||
|
||||
public String getPublisherCountry() {
|
||||
return publisherCountry;
|
||||
}
|
||||
|
||||
public void setPublisherCountry(String publisherCountry) {
|
||||
this.publisherCountry = publisherCountry;
|
||||
}
|
||||
|
||||
|
||||
//tag::embeddable-type-mapping-example[]
|
||||
}
|
||||
//end::embeddable-type-mapping-example[]
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* 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.embeddable;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
public class SimpleEmbeddableTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class<?>[] {
|
||||
Book.class
|
||||
};
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifecycle() {
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
|
||||
Book book = new Book();
|
||||
book.setTitle( "High-Performance Java Persistence" );
|
||||
book.setAuthor( "Vlad Mihalcea" );
|
||||
book.setPublisher(
|
||||
new Publisher(
|
||||
"Amazon",
|
||||
"USA"
|
||||
)
|
||||
);
|
||||
|
||||
entityManager.persist( book );
|
||||
} );
|
||||
}
|
||||
|
||||
//tag::embeddable-type-mapping-example[]
|
||||
@Entity(name = "Book")
|
||||
public static class Book {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String title;
|
||||
|
||||
private String author;
|
||||
|
||||
private Publisher publisher;
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
//end::embeddable-type-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 Publisher getPublisher() {
|
||||
return publisher;
|
||||
}
|
||||
|
||||
public void setPublisher(Publisher publisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
//tag::embeddable-type-mapping-example[]
|
||||
}
|
||||
|
||||
@Embeddable
|
||||
public static class Publisher {
|
||||
|
||||
@Column(name = "publisher_name")
|
||||
private String name;
|
||||
|
||||
@Column(name = "publisher_country")
|
||||
private String country;
|
||||
|
||||
public Publisher(String name, String country) {
|
||||
this.name = name;
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
private Publisher() {}
|
||||
|
||||
//Getters and setters are omitted for brevity
|
||||
//end::embeddable-type-mapping-example[]
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getCountry() {
|
||||
return country;
|
||||
}
|
||||
|
||||
public void setCountry(String country) {
|
||||
this.country = country;
|
||||
}
|
||||
|
||||
//tag::embeddable-type-mapping-example[]
|
||||
}
|
||||
//end::embeddable-type-mapping-example[]
|
||||
}
|
|
@ -296,7 +296,7 @@ public class BaseNonConfigCoreFunctionalTestCase extends BaseUnitTestCase {
|
|||
protected void afterMetadataSourcesApplied(MetadataSources metadataSources) {
|
||||
}
|
||||
|
||||
private void initialize(MetadataBuilder metadataBuilder) {
|
||||
protected void initialize(MetadataBuilder metadataBuilder) {
|
||||
metadataBuilder.enableNewIdentifierGeneratorSupport( true );
|
||||
metadataBuilder.applyImplicitNamingStrategy( ImplicitNamingStrategyLegacyJpaImpl.INSTANCE );
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue