/*
* 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.jpa.test.graphs;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.persistence.Entity;
import javax.persistence.EntityGraph;
import javax.persistence.EntityManager;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Subgraph;
import javax.persistence.Table;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Expression;
import javax.persistence.criteria.Root;
import org.hibernate.Hibernate;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.TestForIssue;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
* @author Christian Bauer
* @author Brett Meyer
*/
public class EntityGraphTest extends BaseEntityManagerFunctionalTestCase {
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Foo.class, Bar.class, Baz.class,
Company.class, Employee.class, Manager.class, Location.class };
}
@Test
@TestForIssue(jiraKey = "HHH-8857")
public void loadMultipleAssociations() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Bar bar = new Bar();
em.persist( bar );
Baz baz = new Baz();
em.persist( baz );
Foo foo = new Foo();
foo.bar = bar;
foo.baz = baz;
em.persist( foo );
em.getTransaction().commit();
em.clear();
em.getTransaction().begin();
EntityGraph<Foo> fooGraph = em.createEntityGraph( Foo.class );
fooGraph.addAttributeNodes( "bar", "baz" );
Map<String, Object> properties = new HashMap<String, Object>();
properties.put( "javax.persistence.loadgraph", fooGraph );
Foo result = em.find( Foo.class, foo.id, properties );
assertTrue( Hibernate.isInitialized( result ) );
assertTrue( Hibernate.isInitialized( result.bar ) );
assertTrue( Hibernate.isInitialized( result.baz ) );
em.getTransaction().commit();
em.close();
}
@Test
public void loadCollection() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Bar bar = new Bar();
em.persist( bar );
Foo foo = new Foo();
foo.bar = bar;
bar.foos.add(foo);
em.persist( foo );
em.getTransaction().commit();
em.clear();
em.getTransaction().begin();
EntityGraph<Bar> barGraph = em.createEntityGraph( Bar.class );
barGraph.addAttributeNodes("foos");
Map<String, Object> properties = new HashMap<String, Object>();
properties.put( "javax.persistence.loadgraph", barGraph);
Bar result = em.find( Bar.class, bar.id, properties );
assertTrue( Hibernate.isInitialized( result ) );
assertTrue( Hibernate.isInitialized( result.foos ) );
em.getTransaction().commit();
em.close();
}
@Test
public void loadInverseCollection() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Bar bar = new Bar();
em.persist( bar );
Baz baz = new Baz();
em.persist( baz );
Foo foo = new Foo();
foo.bar = bar;
foo.baz = baz;
bar.foos.add(foo);
baz.foos.add(foo);
em.persist( foo );
em.getTransaction().commit();
em.clear();
em.getTransaction().begin();
EntityGraph<Foo> fooGraph = em.createEntityGraph( Foo.class );
fooGraph.addAttributeNodes("bar");
fooGraph.addAttributeNodes("baz");
Subgraph<Bar> barGraph = fooGraph.addSubgraph("bar", Bar.class);
barGraph.addAttributeNodes("foos");
Map<String, Object> properties = new HashMap<String, Object>();
properties.put( "javax.persistence.loadgraph", fooGraph );
Foo result = em.find( Foo.class, foo.id, properties );
assertTrue( Hibernate.isInitialized( result ) );
assertTrue( Hibernate.isInitialized( result.bar ) );
assertTrue( Hibernate.isInitialized( result.bar.foos) );
assertTrue( Hibernate.isInitialized( result.baz ) );
// sanity check -- ensure the only bi-directional fetch was the one identified by the graph
assertFalse( Hibernate.isInitialized( result.baz.foos) );
em.getTransaction().commit();
em.close();
}
/**
* JPA 2.1 spec: "Add a node to the graph that corresponds to a managed type with inheritance. This allows for
* multiple subclass subgraphs to be defined for this node of the entity graph. Subclass subgraphs will
* automatically include the specified attributes of superclass subgraphs."
*/
@Test
@TestForIssue(jiraKey = "HHH-8640")
public void inheritanceTest() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Manager manager = new Manager();
em.persist( manager );
Employee employee = new Employee();
employee.friends.add( manager );
employee.managers.add( manager );
em.persist( employee );
Company company = new Company();
company.employees.add( employee );
company.employees.add( manager );
em.persist( company );
em.getTransaction().commit();
em.clear();
em.getTransaction().begin();
EntityGraph<Company> entityGraph = em.createEntityGraph( Company.class );
Subgraph<Employee> subgraph = entityGraph.addSubgraph( "employees" );
subgraph.addAttributeNodes( "managers" );
subgraph.addAttributeNodes( "friends" );
Subgraph<Manager> subSubgraph = subgraph.addSubgraph( "managers", Manager.class );
subSubgraph.addAttributeNodes( "managers" );
subSubgraph.addAttributeNodes( "friends" );
Map<String, Object> properties = new HashMap<String, Object>();
properties.put( "javax.persistence.loadgraph", entityGraph );
Company result = em.find( Company.class, company.id, properties );
assertTrue( Hibernate.isInitialized( result ) );
assertTrue( Hibernate.isInitialized( result.employees ) );
assertEquals( result.employees.size(), 2 );
for (Employee resultEmployee : result.employees) {
assertTrue( Hibernate.isInitialized( resultEmployee.managers ) );
assertTrue( Hibernate.isInitialized( resultEmployee.friends ) );
}
em.getTransaction().commit();
em.close();
}
@Test
@TestForIssue(jiraKey = "HHH-9080")
public void attributeNodeInheritanceTest() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Manager manager = new Manager();
em.persist( manager );
Employee employee = new Employee();
manager.friends.add( employee);
em.persist( employee );
Manager anotherManager = new Manager();
manager.managers.add(anotherManager);
em.persist( anotherManager );
em.getTransaction().commit();
em.clear();
em.getTransaction().begin();
EntityGraph<Manager> entityGraph = em.createEntityGraph( Manager.class );
entityGraph.addAttributeNodes( "friends" );
entityGraph.addAttributeNodes( "managers" );
Map<String, Object> properties = new HashMap<String, Object>();
properties.put( "javax.persistence.loadgraph", entityGraph );
Manager result = em.find( Manager.class, manager.id, properties );
assertTrue( Hibernate.isInitialized( result ) );
assertTrue( Hibernate.isInitialized( result.friends ) );
assertEquals( result.friends.size(), 1 );
assertTrue( Hibernate.isInitialized( result.managers) );
assertEquals( result.managers.size(), 1 );
em.getTransaction().commit();
em.close();
}
@Test
@TestForIssue(jiraKey = "HHH-9735")
public void loadIsMemeberQueriedCollection() {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Bar bar = new Bar();
em.persist( bar );
Foo foo = new Foo();
foo.bar = bar;
bar.foos.add(foo);
em.persist( foo );
em.getTransaction().commit();
em.clear();
em.getTransaction().begin();
foo = em.find(Foo.class, foo.id);
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Bar> cq = cb.createQuery(Bar.class);
Root<Bar> from = cq.from(Bar.class);
Expression<Set<Foo>> foos = from.get("foos");
cq.where(cb.isMember(foo, foos));
TypedQuery<Bar> query = em.createQuery(cq);
EntityGraph<Bar> barGraph = em.createEntityGraph( Bar.class );
barGraph.addAttributeNodes("foos");
query.setHint("javax.persistence.loadgraph", barGraph);
Bar result = query.getSingleResult();
assertTrue( Hibernate.isInitialized( result ) );
assertTrue( Hibernate.isInitialized( result.foos ) );
em.getTransaction().commit();
em.close();
}
@Entity
@Table(name = "foo")
public static class Foo {
@Id
@GeneratedValue
public Integer id;
@ManyToOne(fetch = FetchType.LAZY)
public Bar bar;
@ManyToOne(fetch = FetchType.LAZY)
public Baz baz;
}
@Entity
@Table(name = "bar")
public static class Bar {
@Id
@GeneratedValue
public Integer id;
@OneToMany(mappedBy = "bar")
public Set<Foo> foos = new HashSet<Foo>();
}
@Entity
@Table(name = "baz")
public static class Baz {
@Id
@GeneratedValue
public Integer id;
@OneToMany(mappedBy = "baz")
public Set<Foo> foos = new HashSet<Foo>();
}
}