HHH-11186 - Add examples for all Hibernate annotations
Document @NamedSubgraph
This commit is contained in:
parent
9039291288
commit
6307a47c13
|
@ -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.
|
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]]
|
[[annotations-jpa-onetomany]]
|
||||||
==== `@OneToMany`
|
==== `@OneToMany`
|
||||||
|
|
|
@ -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.
|
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]]
|
[[fetching-strategies-dynamic-fetching-profile]]
|
||||||
=== Dynamic fetching via Hibernate profiles
|
=== Dynamic fetching via Hibernate profiles
|
||||||
|
|
||||||
|
|
|
@ -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]
|
|
@ -17,10 +17,13 @@ import javax.persistence.ManyToMany;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.NamedAttributeNode;
|
import javax.persistence.NamedAttributeNode;
|
||||||
import javax.persistence.NamedEntityGraph;
|
import javax.persistence.NamedEntityGraph;
|
||||||
|
import javax.persistence.NamedSubgraph;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.QueryHint;
|
||||||
|
|
||||||
import org.hibernate.annotations.ColumnTransformer;
|
import org.hibernate.annotations.ColumnTransformer;
|
||||||
import org.hibernate.annotations.NaturalId;
|
import org.hibernate.annotations.NaturalId;
|
||||||
|
import org.hibernate.annotations.QueryHints;
|
||||||
import org.hibernate.dialect.H2Dialect;
|
import org.hibernate.dialect.H2Dialect;
|
||||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||||
|
|
||||||
|
@ -30,7 +33,9 @@ import org.junit.Test;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
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.assertNotNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Vlad Mihalcea
|
* @author Vlad Mihalcea
|
||||||
|
@ -72,6 +77,10 @@ public class GraphFetchingTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
employee2.department = department;
|
employee2.department = department;
|
||||||
entityManager.persist( employee2 );
|
entityManager.persist( employee2 );
|
||||||
|
|
||||||
|
Project project = new Project();
|
||||||
|
project.id = 1L;
|
||||||
|
project.employees.add( employee1 );
|
||||||
|
entityManager.persist( project );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||||
|
@ -90,6 +99,20 @@ public class GraphFetchingTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
assertNotNull(employee);
|
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")
|
@Entity(name = "Department")
|
||||||
|
@ -102,6 +125,22 @@ public class GraphFetchingTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
private List<Employee> employees = new ArrayList<>();
|
private List<Employee> employees = new ArrayList<>();
|
||||||
|
|
||||||
//Getters and setters omitted for brevity
|
//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[]
|
//tag::fetching-strategies-dynamic-fetching-entity-graph-mapping-example[]
|
||||||
|
@ -134,10 +173,69 @@ public class GraphFetchingTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
private List<Project> projects = new ArrayList<>();
|
private List<Project> projects = new ArrayList<>();
|
||||||
|
|
||||||
//Getters and setters omitted for brevity
|
//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")
|
@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
|
@Id
|
||||||
private Long id;
|
private Long id;
|
||||||
|
@ -146,5 +244,24 @@ public class GraphFetchingTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
private List<Employee> employees = new ArrayList<>();
|
private List<Employee> employees = new ArrayList<>();
|
||||||
|
|
||||||
//Getters and setters omitted for brevity
|
//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[]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue