/* * 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>(); } }