HHH-11186 - Add examples for all Hibernate annotations

Document more annotations:

- @JoinFormula
This commit is contained in:
Vlad Mihalcea 2016-12-02 13:28:18 +02:00
parent 0ab2992a9a
commit c83efda49b
5 changed files with 293 additions and 0 deletions

View File

@ -876,6 +876,8 @@ The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibern
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/JoinFormula.html[`@JoinFormula`] annotation is used as a replacement for <<annotations-jpa-joincolumn>> when the association does not have a dedicated FOREIGN KEY column.
See the <<chapters/domain/basic_types.adoc#mapping-JoinFormula-example,`@JoinFormula` mapping>> section for more info.
[[annotations-hibernate-lazycollection]]
==== `@LazyCollection`

View File

@ -1832,3 +1832,52 @@ include::{extrasdir}/basic/mapping-column-many-to-any-persistence-example.sql[]
----
====
[[mapping-JoinFormula]]
==== `@JoinFormula` mapping
The https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/javadocs/org/hibernate/annotations/JoinFormula.html[`@JoinFormula`] annotation is used to customize the join between a child Foreign Key and a parent row Primary Key.
[[mapping-JoinFormula-example]]
.`@JoinFormula` mapping usage
====
[source, JAVA, indent=0]
----
include::{sourcedir}/basic/JoinFormulaTest.java[tags=mapping-JoinFormula-example]
----
[source, SQL, indent=0]
----
include::{extrasdir}/basic/mapping-JoinFormula-example.sql[]
----
====
The `country` association in the `User` entity is mapped by the country identifier provided by the `phoneNumber` property.
Considering we have the following entities:
[[mapping-JoinFormula-persistence-example]]
.`@JoinFormula` mapping usage
====
[source, JAVA, indent=0]
----
include::{sourcedir}/basic/JoinFormulaTest.java[tags=mapping-JoinFormula-persistence-example]
----
====
When fetching the `User` entities, the `country` property is mapped by the `@JoinFormula` expression:
[[mapping-JoinFormula-fetching-example]]
.`@JoinFormula` mapping usage
====
[source, JAVA, indent=0]
----
include::{sourcedir}/basic/JoinFormulaTest.java[tags=mapping-JoinFormula-fetching-example]
----
[source, SQL, indent=0]
----
include::{extrasdir}/basic/mapping-JoinFormula-fetching-example.sql[]
----
====
Therefore, the `@JoinFormula` annotation is used to define a custom join association between the parent-child association.

View File

@ -0,0 +1,13 @@
CREATE TABLE countries (
id int4 NOT NULL,
name VARCHAR(255),
PRIMARY KEY ( id )
)
CREATE TABLE users (
id int8 NOT NULL,
firstName VARCHAR(255),
lastName VARCHAR(255),
phoneNumber VARCHAR(255),
PRIMARY KEY ( id )
)

View File

@ -0,0 +1,37 @@
-- Fetch User entities
SELECT
u.id as id1_1_0_,
u.firstName as firstNam2_1_0_,
u.lastName as lastName3_1_0_,
u.phoneNumber as phoneNum4_1_0_,
REGEXP_REPLACE(u.phoneNumber, '\+(\d+)-.*', '\1')::int as formula1_0_,
c.id as id1_0_1_,
c.name as name2_0_1_
FROM
users u
LEFT OUTER JOIN
countries c
ON REGEXP_REPLACE(u.phoneNumber, '\+(\d+)-.*', '\1')::int = c.id
WHERE
u.id=?
-- binding parameter [1] as [BIGINT] - [1]
SELECT
u.id as id1_1_0_,
u.firstName as firstNam2_1_0_,
u.lastName as lastName3_1_0_,
u.phoneNumber as phoneNum4_1_0_,
REGEXP_REPLACE(u.phoneNumber, '\+(\d+)-.*', '\1')::int as formula1_0_,
c.id as id1_0_1_,
c.name as name2_0_1_
FROM
users u
LEFT OUTER JOIN
countries c
ON REGEXP_REPLACE(u.phoneNumber, '\+(\d+)-.*', '\1')::int = c.id
WHERE
u.id=?
-- binding parameter [1] as [BIGINT] - [2]

View File

@ -0,0 +1,192 @@
/*
* 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.basic;
import java.util.Objects;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.hibernate.annotations.JoinFormula;
import org.hibernate.dialect.PostgreSQL82Dialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.RequiresDialect;
import org.junit.Test;
import org.jboss.logging.Logger;
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
import static org.junit.Assert.assertEquals;
/**
* @author Vlad Mihalcea
*/
@RequiresDialect(PostgreSQL82Dialect.class)
public class JoinFormulaTest extends BaseEntityManagerFunctionalTestCase {
private static final Logger log = Logger.getLogger( JoinFormulaTest.class );
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Country.class,
User.class
};
}
@Test
public void testLifecycle() {
//tag::mapping-JoinFormula-persistence-example[]
Country US = new Country();
US.setId( 1 );
US.setName( "United States" );
Country Romania = new Country();
Romania.setId( 40 );
Romania.setName( "Romania" );
doInJPA( this::entityManagerFactory, entityManager -> {
entityManager.persist( US );
entityManager.persist( Romania );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
User user1 = new User( );
user1.setId( 1L );
user1.setFirstName( "John" );
user1.setLastName( "Doe" );
user1.setPhoneNumber( "+1-234-5678" );
entityManager.persist( user1 );
User user2 = new User( );
user2.setId( 2L );
user2.setFirstName( "Vlad" );
user2.setLastName( "Mihalcea" );
user2.setPhoneNumber( "+40-123-4567" );
entityManager.persist( user2 );
} );
//end::mapping-JoinFormula-persistence-example[]
//tag::mapping-JoinFormula-fetching-example[]
doInJPA( this::entityManagerFactory, entityManager -> {
log.info( "Fetch User entities" );
User john = entityManager.find( User.class, 1L );
assertEquals( US, john.getCountry());
User vlad = entityManager.find( User.class, 2L );
assertEquals( Romania, vlad.getCountry());
} );
//end::mapping-JoinFormula-fetching-example[]
}
//tag::mapping-JoinFormula-example[]
@Entity(name = "User")
@Table(name = "users")
public static class User {
@Id
private Long id;
private String firstName;
private String lastName;
private String phoneNumber;
@ManyToOne
@JoinFormula( "REGEXP_REPLACE(phoneNumber, '\\+(\\d+)-.*', '\\1')::int" )
private Country country;
//Getters and setters omitted for brevity
//end::mapping-JoinFormula-example[]
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public Country getCountry() {
return country;
}
//tag::mapping-JoinFormula-example[]
}
@Entity(name = "Country")
@Table(name = "countries")
public static class Country {
@Id
private Integer id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( !( o instanceof Country ) ) {
return false;
}
Country country = (Country) o;
return Objects.equals( getId(), country.getId() );
}
@Override
public int hashCode() {
return Objects.hash( getId() );
}
}
//end::mapping-JoinFormula-example[]
}