HHH-11186 - Add examples for all Hibernate annotations

Document @NamedSubgraph
This commit is contained in:
Vlad Mihalcea 2017-06-07 17:24:00 +03:00
parent 9039291288
commit 6307a47c13
4 changed files with 176 additions and 2 deletions

View File

@ -408,7 +408,7 @@ See the <<chapters/query/native/Native.adoc#sql-sp-named-query, Using named quer
The http://docs.oracle.com/javaee/7/api/javax/persistence/NamedSubgraph.html[`@NamedSubgraph`] annotation used to specify a subgraph in an Entity Graph.
//TODO: Add example
See the <<chapters/fetching/Fetching.adoc#fetching-strategies-dynamic-fetching-entity-subgraph, Fetch subgraph>> section for more info.
[[annotations-jpa-onetomany]]
==== `@OneToMany`

View File

@ -208,6 +208,40 @@ Entity graphs are the way to override the EAGER fetching associations at runtime
With JPQL, if an EAGER association is omitted, Hibernate will issue a secondary select for every association needed to be fetched eagerly.
====
[[fetching-strategies-dynamic-fetching-entity-subgraph]]
==== JPA entity subgraphs
An entity graph specifies which attributes to be fetched, but it limited to a single entity only.
To fetch associations from a child entity, you need to use the http://docs.oracle.com/javaee/7/api/javax/persistence/NamedSubgraph.html[`@NamedSubgraph`] annotation.
If we have a `Project` parent entity which has an `employees` child associations,
and we'd like to fetch the `department` for the `Employee` child association.
[[fetching-strategies-dynamic-fetching-entity-subgraph-mapping-example]]
.Fetch graph with a subgraph mapping
====
[source, JAVA, indent=0]
----
include::{sourcedir}/GraphFetchingTest.java[tags=fetching-strategies-dynamic-fetching-entity-subgraph-mapping-example]
----
====
When fetching this entity graph, Hibernate generates the following SQL query:
[[fetching-strategies-dynamic-fetching-entity-subgraph-example]]
.Fetch graph with a subgraph mapping
====
[source, JAVA, indent=0]
----
include::{sourcedir}/GraphFetchingTest.java[tags=fetching-strategies-dynamic-fetching-entity-subgraph-example]
----
[source, SQL, indent=0]
----
include::{extrasdir}/fetching-strategies-dynamic-fetching-entity-subgraph-example.sql[]
----
====
[[fetching-strategies-dynamic-fetching-profile]]
=== Dynamic fetching via Hibernate profiles

View File

@ -0,0 +1,23 @@
select
p.id as id1_2_0_, e.id as id1_1_1_, d.id as id1_0_2_,
e.accessLevel as accessLe2_1_1_,
e.department_id as departme5_1_1_,
decrypt( 'AES', '00', e.pswd ) as pswd3_1_1_,
e.username as username4_1_1_,
p_e.projects_id as projects1_3_0__,
p_e.employees_id as employee2_3_0__
from
Project p
inner join
Project_Employee p_e
on p.id=p_e.projects_id
inner join
Employee e
on p_e.employees_id=e.id
inner join
Department d
on e.department_id=d.id
where
p.id = ?
-- binding parameter [1] as [BIGINT] - [1]

View File

@ -17,10 +17,13 @@ import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.NamedAttributeNode;
import javax.persistence.NamedEntityGraph;
import javax.persistence.NamedSubgraph;
import javax.persistence.OneToMany;
import javax.persistence.QueryHint;
import org.hibernate.annotations.ColumnTransformer;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.QueryHints;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
@ -30,7 +33,9 @@ import org.junit.Test;
import org.jboss.logging.Logger;
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.assertSame;
/**
* @author Vlad Mihalcea
@ -72,6 +77,10 @@ public class GraphFetchingTest extends BaseEntityManagerFunctionalTestCase {
employee2.department = department;
entityManager.persist( employee2 );
Project project = new Project();
project.id = 1L;
project.employees.add( employee1 );
entityManager.persist( project );
} );
doInJPA( this::entityManagerFactory, entityManager -> {
@ -90,6 +99,20 @@ public class GraphFetchingTest extends BaseEntityManagerFunctionalTestCase {
assertNotNull(employee);
} );
//tag::fetching-strategies-dynamic-fetching-entity-subgraph-example[]
Project project = doInJPA( this::entityManagerFactory, entityManager -> {
return entityManager.find(
Project.class,
1L,
Collections.singletonMap(
"javax.persistence.fetchgraph",
entityManager.getEntityGraph( "project.employees" )
)
);
} );
//end::fetching-strategies-dynamic-fetching-entity-subgraph-example[]
assertEquals(1, project.getEmployees().size());
assertEquals( Long.valueOf( 1L ), project.getEmployees().get( 0 ).getDepartment().getId() );
}
@Entity(name = "Department")
@ -102,6 +125,22 @@ public class GraphFetchingTest extends BaseEntityManagerFunctionalTestCase {
private List<Employee> employees = new ArrayList<>();
//Getters and setters omitted for brevity
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
//tag::fetching-strategies-dynamic-fetching-entity-graph-mapping-example[]
@ -134,10 +173,69 @@ public class GraphFetchingTest extends BaseEntityManagerFunctionalTestCase {
private List<Project> projects = new ArrayList<>();
//Getters and setters omitted for brevity
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAccessLevel() {
return accessLevel;
}
public void setAccessLevel(int accessLevel) {
this.accessLevel = accessLevel;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
public List<Project> getProjects() {
return projects;
}
public void setProjects(List<Project> projects) {
this.projects = projects;
}
}
//tag::fetching-strategies-dynamic-fetching-entity-subgraph-mapping-example[]
@Entity(name = "Project")
public class Project {
@NamedEntityGraph(name = "project.employees",
attributeNodes = @NamedAttributeNode(
value = "employees",
subgraph = "project.employees.department"
),
subgraphs = @NamedSubgraph(
name = "project.employees.department",
attributeNodes = @NamedAttributeNode( "department" )
)
)
public static class Project {
@Id
private Long id;
@ -146,5 +244,24 @@ public class GraphFetchingTest extends BaseEntityManagerFunctionalTestCase {
private List<Employee> employees = new ArrayList<>();
//Getters and setters omitted for brevity
//end::fetching-strategies-dynamic-fetching-entity-subgraph-mapping-example[]
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
//tag::fetching-strategies-dynamic-fetching-entity-subgraph-mapping-example[]
}
//end::fetching-strategies-dynamic-fetching-entity-subgraph-mapping-example[]
}