diff --git a/documentation/src/test/java/org/hibernate/userguide/fetching/GraphParsingTest.java b/documentation/src/test/java/org/hibernate/userguide/fetching/GraphParsingTest.java index 47ca10fdf3..32328d7fae 100644 --- a/documentation/src/test/java/org/hibernate/userguide/fetching/GraphParsingTest.java +++ b/documentation/src/test/java/org/hibernate/userguide/fetching/GraphParsingTest.java @@ -16,7 +16,7 @@ import javax.persistence.ManyToOne; import javax.persistence.TypedQuery; import org.hibernate.dialect.H2Dialect; -import org.hibernate.orm.test.loading.entitygraph.parser.AbstractEntityGraphTest; +import org.hibernate.orm.test.entitygraph.parser.AbstractEntityGraphTest; import org.hibernate.graph.GraphParser; import org.hibernate.graph.EntityGraphs; import org.hibernate.graph.GraphSemantic; diff --git a/hibernate-core/src/main/.gitignore b/hibernate-core/src/main/.gitignore index 6501858264..7f7df69779 100644 --- a/hibernate-core/src/main/.gitignore +++ b/hibernate-core/src/main/.gitignore @@ -1,2 +1,5 @@ ## Ignore IntelliJ Antlr Plugin's output gen/ + +## Ignore other generated code (e.g. Logger) +generated/ diff --git a/hibernate-core/src/main/java/org/hibernate/graph/SubGraph.java b/hibernate-core/src/main/java/org/hibernate/graph/SubGraph.java index fdb4e93784..6429139e74 100644 --- a/hibernate-core/src/main/java/org/hibernate/graph/SubGraph.java +++ b/hibernate-core/src/main/java/org/hibernate/graph/SubGraph.java @@ -9,7 +9,7 @@ package org.hibernate.graph; import java.util.List; import javax.persistence.metamodel.Attribute; -import org.hibernate.NotYetImplementedFor6Exception; +import org.hibernate.metamodel.model.domain.PersistentAttribute; /** * Hibernate extension to the JPA entity-graph Subgraph contract. @@ -43,53 +43,40 @@ public interface SubGraph extends Graph, javax.persistence.Subgraph { } for ( Attribute node : attribute ) { -// addAttributeNode( node ); - throw new NotYetImplementedFor6Exception( getClass() ); - + assert node instanceof PersistentAttribute; + addAttributeNode( (PersistentAttribute) node ); } } @Override - @SuppressWarnings("unchecked") default SubGraph addSubgraph(Attribute attribute) { - throw new NotYetImplementedFor6Exception( getClass() ); -// return addSubGraph( attribute ); + return addSubGraph( (PersistentAttribute) attribute ); } @Override - @SuppressWarnings("unchecked") default SubGraph addSubgraph(Attribute attribute, Class type) { -// return addSubGraph( attribute, type ); - throw new NotYetImplementedFor6Exception( getClass() ); + return addSubGraph( (PersistentAttribute) attribute, type ); } @Override - @SuppressWarnings("unchecked") default SubGraph addSubgraph(String name) { return addSubGraph( name ); } @Override - @SuppressWarnings("unchecked") default SubGraph addSubgraph(String name, Class type) { return addSubGraph( name, type ); } @Override - @SuppressWarnings("unchecked") default SubGraph addKeySubgraph(Attribute attribute) { - throw new NotYetImplementedFor6Exception( getClass() ); - -// return addKeySubGraph( attribute ); + return addKeySubGraph( (PersistentAttribute) attribute ); } @Override - @SuppressWarnings("unchecked") default SubGraph addKeySubgraph(Attribute attribute, Class type) { -// return addKeySubGraph( attribute, type ); - throw new NotYetImplementedFor6Exception( getClass() ); - + return addKeySubGraph( (PersistentAttribute) attribute, type ); } @Override @@ -98,13 +85,11 @@ public interface SubGraph extends Graph, javax.persistence.Subgraph { } @Override - @SuppressWarnings("unchecked") default SubGraph addKeySubgraph(String name, Class type) { return addKeySubGraph( name, type ); } @Override - @SuppressWarnings("unchecked") default Class getClassType() { return getGraphedType().getJavaType(); } diff --git a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java index 166606edb6..0f811e332e 100644 --- a/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/loader/ast/internal/LoaderSelectBuilder.java @@ -8,7 +8,6 @@ package org.hibernate.loader.ast.internal; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -20,14 +19,18 @@ import org.hibernate.LockOptions; import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchTiming; import org.hibernate.engine.profile.FetchProfile; +import org.hibernate.engine.spi.EffectiveEntityGraph; import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SubselectFetch; +import org.hibernate.graph.GraphSemantic; +import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.internal.FilterHelper; import org.hibernate.internal.util.MutableInteger; import org.hibernate.loader.ast.spi.Loadable; import org.hibernate.loader.ast.spi.Loader; import org.hibernate.metamodel.mapping.BasicValuedModelPart; +import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; @@ -187,14 +190,20 @@ public class LoaderSelectBuilder { this.cachedDomainResult = cachedDomainResult; this.numberOfKeysToLoad = numberOfKeysToLoad; this.loadQueryInfluencers = loadQueryInfluencers; - if ( loadQueryInfluencers != null - && loadQueryInfluencers.getEffectiveEntityGraph() != null - && loadQueryInfluencers.getEffectiveEntityGraph().getSemantic() != null ) { - this.entityGraphTraversalState = new StandardEntityGraphTraversalStateImpl( loadQueryInfluencers.getEffectiveEntityGraph() ); - } - else { - this.entityGraphTraversalState = null; + + EntityGraphTraversalState entityGraphTraversalState = null; + if ( loadQueryInfluencers != null ) { + final EffectiveEntityGraph effectiveEntityGraph = loadQueryInfluencers.getEffectiveEntityGraph(); + if ( effectiveEntityGraph != null ) { + final GraphSemantic graphSemantic = effectiveEntityGraph.getSemantic(); + final RootGraphImplementor rootGraphImplementor = effectiveEntityGraph.getGraph(); + if ( graphSemantic != null && rootGraphImplementor != null ) { + entityGraphTraversalState = new StandardEntityGraphTraversalStateImpl( graphSemantic, rootGraphImplementor ); + } + } } + this.entityGraphTraversalState = entityGraphTraversalState; + this.lockOptions = lockOptions != null ? lockOptions : LockOptions.NONE; this.jdbcParameterConsumer = jdbcParameterConsumer; } @@ -473,25 +482,30 @@ public class LoaderSelectBuilder { EntityGraphTraversalState.TraversalResult traversalResult = null; - // 'entity graph' takes precedence over 'fetch profile' - if ( entityGraphTraversalState != null) { - traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable ); - fetchTiming = traversalResult.getFetchStrategy(); - joined = traversalResult.isJoined(); - } - else if ( loadQueryInfluencers.hasEnabledFetchProfiles() ) { - if ( fetchParent instanceof EntityResultGraphNode ) { - final EntityResultGraphNode entityFetchParent = (EntityResultGraphNode) fetchParent; - final EntityMappingType entityMappingType = entityFetchParent.getEntityValuedModelPart().getEntityMappingType(); - final String fetchParentEntityName = entityMappingType.getEntityName(); - final String fetchableRole = fetchParentEntityName + "." + fetchable.getFetchableName(); + if ( ! (fetchable instanceof CollectionPart ) ) { + // 'entity graph' takes precedence over 'fetch profile' + if ( entityGraphTraversalState != null ) { + traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable ); + fetchTiming = traversalResult.getFetchStrategy(); + joined = traversalResult.isJoined(); + } + else if ( loadQueryInfluencers.hasEnabledFetchProfiles() ) { + if ( fetchParent instanceof EntityResultGraphNode ) { + final EntityResultGraphNode entityFetchParent = (EntityResultGraphNode) fetchParent; + final EntityMappingType entityMappingType = entityFetchParent.getEntityValuedModelPart() + .getEntityMappingType(); + final String fetchParentEntityName = entityMappingType.getEntityName(); + final String fetchableRole = fetchParentEntityName + "." + fetchable.getFetchableName(); - for ( String enabledFetchProfileName : loadQueryInfluencers.getEnabledFetchProfileNames() ) { - final FetchProfile enabledFetchProfile = creationContext.getSessionFactory().getFetchProfile( enabledFetchProfileName ); - final org.hibernate.engine.profile.Fetch profileFetch = enabledFetchProfile.getFetchByRole( fetchableRole ); + for ( String enabledFetchProfileName : loadQueryInfluencers.getEnabledFetchProfileNames() ) { + final FetchProfile enabledFetchProfile = creationContext.getSessionFactory() + .getFetchProfile( enabledFetchProfileName ); + final org.hibernate.engine.profile.Fetch profileFetch = enabledFetchProfile.getFetchByRole( + fetchableRole ); - fetchTiming = FetchTiming.IMMEDIATE; - joined = joined || profileFetch.getStyle() == org.hibernate.engine.profile.Fetch.Style.JOIN; + fetchTiming = FetchTiming.IMMEDIATE; + joined = joined || profileFetch.getStyle() == org.hibernate.engine.profile.Fetch.Style.JOIN; + } } } } @@ -509,8 +523,12 @@ public class LoaderSelectBuilder { } } + boolean changeFetchDepth = !( fetchable instanceof BasicValuedModelPart ) + && !( fetchable instanceof EmbeddedAttributeMapping ) + && !( fetchable instanceof CollectionPart ); + try { - if ( !( fetchable instanceof BasicValuedModelPart ) && !( fetchable instanceof EmbeddedAttributeMapping ) ) { + if ( changeFetchDepth ) { fetchDepth++; } final Fetch fetch = fetchable.generateFetch( @@ -541,10 +559,10 @@ public class LoaderSelectBuilder { } } finally { - if ( !( fetchable instanceof BasicValuedModelPart ) && !( fetchable instanceof EmbeddedAttributeMapping ) ) { + if ( changeFetchDepth ) { fetchDepth--; } - if ( entityGraphTraversalState != null ) { + if ( entityGraphTraversalState != null && traversalResult != null ) { entityGraphTraversalState.backtrack( traversalResult.getPreviousContext() ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/StandardSqmSelectTranslator.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/StandardSqmSelectTranslator.java index 9861ac352c..c95498c553 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/StandardSqmSelectTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/StandardSqmSelectTranslator.java @@ -20,10 +20,12 @@ import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.engine.FetchTiming; import org.hibernate.engine.profile.FetchProfile; import org.hibernate.engine.spi.LoadQueryInfluencers; +import org.hibernate.graph.spi.AppliedGraph; import org.hibernate.internal.FilterHelper; import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.Stack; import org.hibernate.internal.util.collections.StandardStack; +import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPartContainer; @@ -106,10 +108,10 @@ public class StandardSqmSelectTranslator SqlAstCreationContext creationContext) { super( creationContext, queryOptions, fetchInfluencers, domainParameterXref, domainParameterBindings ); - if ( fetchInfluencers != null - && fetchInfluencers.getEffectiveEntityGraph() != null - && fetchInfluencers.getEffectiveEntityGraph().getSemantic() != null ) { - this.entityGraphTraversalState = new StandardEntityGraphTraversalStateImpl( fetchInfluencers.getEffectiveEntityGraph() ); + final AppliedGraph appliedGraph = queryOptions.getAppliedGraph(); + if ( appliedGraph != null && appliedGraph.getSemantic() != null && appliedGraph.getGraph() != null ) { + this.entityGraphTraversalState = new StandardEntityGraphTraversalStateImpl( + appliedGraph.getSemantic(), appliedGraph.getGraph() ); } else { this.entityGraphTraversalState = null; @@ -331,24 +333,29 @@ public class StandardSqmSelectTranslator // there was not an explicit fetch in the SQM alias = null; - if ( entityGraphTraversalState != null ) { - traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable ); - fetchTiming = traversalResult.getFetchStrategy(); - joined = traversalResult.isJoined(); - } - else if ( getLoadQueryInfluencers().hasEnabledFetchProfiles() ) { - if ( fetchParent instanceof EntityResultGraphNode ) { - final EntityResultGraphNode entityFetchParent = (EntityResultGraphNode) fetchParent; - final EntityMappingType entityMappingType = entityFetchParent.getEntityValuedModelPart().getEntityMappingType(); - final String fetchParentEntityName = entityMappingType.getEntityName(); - final String fetchableRole = fetchParentEntityName + "." + fetchable.getFetchableName(); + if ( !( fetchable instanceof CollectionPart ) ) { + if ( entityGraphTraversalState != null ) { + traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable ); + fetchTiming = traversalResult.getFetchStrategy(); + joined = traversalResult.isJoined(); + } + else if ( getLoadQueryInfluencers().hasEnabledFetchProfiles() ) { + if ( fetchParent instanceof EntityResultGraphNode ) { + final EntityResultGraphNode entityFetchParent = (EntityResultGraphNode) fetchParent; + final EntityMappingType entityMappingType = entityFetchParent.getEntityValuedModelPart() + .getEntityMappingType(); + final String fetchParentEntityName = entityMappingType.getEntityName(); + final String fetchableRole = fetchParentEntityName + "." + fetchable.getFetchableName(); - for ( String enabledFetchProfileName : getLoadQueryInfluencers().getEnabledFetchProfileNames() ) { - final FetchProfile enabledFetchProfile = getCreationContext().getSessionFactory().getFetchProfile( enabledFetchProfileName ); - final org.hibernate.engine.profile.Fetch profileFetch = enabledFetchProfile.getFetchByRole( fetchableRole ); + for ( String enabledFetchProfileName : getLoadQueryInfluencers().getEnabledFetchProfileNames() ) { + final FetchProfile enabledFetchProfile = getCreationContext().getSessionFactory() + .getFetchProfile( enabledFetchProfileName ); + final org.hibernate.engine.profile.Fetch profileFetch = enabledFetchProfile.getFetchByRole( + fetchableRole ); - fetchTiming = FetchTiming.IMMEDIATE; - joined = joined || profileFetch.getStyle() == org.hibernate.engine.profile.Fetch.Style.JOIN; + fetchTiming = FetchTiming.IMMEDIATE; + joined = joined || profileFetch.getStyle() == org.hibernate.engine.profile.Fetch.Style.JOIN; + } } } } diff --git a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardEntityGraphTraversalStateImpl.java b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardEntityGraphTraversalStateImpl.java index c694005b16..e0a83bf0e1 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardEntityGraphTraversalStateImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/results/internal/StandardEntityGraphTraversalStateImpl.java @@ -7,14 +7,15 @@ package org.hibernate.sql.results.internal; import java.util.Map; +import java.util.Objects; import javax.persistence.metamodel.PluralAttribute; import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchTiming; -import org.hibernate.engine.spi.EffectiveEntityGraph; import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.spi.AttributeNodeImplementor; import org.hibernate.graph.spi.GraphImplementor; +import org.hibernate.graph.spi.RootGraphImplementor; import org.hibernate.graph.spi.SubGraphImplementor; import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.mapping.EntityMappingType; @@ -34,13 +35,11 @@ public class StandardEntityGraphTraversalStateImpl implements EntityGraphTravers private final GraphSemantic graphSemantic; private GraphImplementor currentGraphContext; - public StandardEntityGraphTraversalStateImpl(EffectiveEntityGraph effectiveEntityGraph) { - assert effectiveEntityGraph != null; - if ( effectiveEntityGraph.getSemantic() == null ) { - throw new IllegalArgumentException( "The graph has not defined semantic: " + effectiveEntityGraph ); - } - this.graphSemantic = effectiveEntityGraph.getSemantic(); - this.currentGraphContext = effectiveEntityGraph.getGraph(); + public StandardEntityGraphTraversalStateImpl(GraphSemantic graphSemantic, RootGraphImplementor rootGraphImplementor) { + Objects.requireNonNull(graphSemantic, "graphSemantic cannot be null"); + Objects.requireNonNull( rootGraphImplementor, "rootGraphImplementor cannot be null" ); + this.graphSemantic = graphSemantic; + this.currentGraphContext = rootGraphImplementor; } @Override @@ -50,6 +49,8 @@ public class StandardEntityGraphTraversalStateImpl implements EntityGraphTravers @Override public TraversalResult traverse(FetchParent fetchParent, Fetchable fetchable, boolean exploreKeySubgraph) { + assert !(fetchable instanceof CollectionPart); + final GraphImplementor previousContextRoot = currentGraphContext; AttributeNodeImplementor attributeNode = null; if ( appliesTo( fetchParent ) ) { diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/BasicEntityGraphTests.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/BasicEntityGraphTests.java deleted file mode 100644 index 1ea8f7284e..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/BasicEntityGraphTests.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs; - -import javax.persistence.AttributeNode; -import javax.persistence.Entity; -import javax.persistence.EntityGraph; -import javax.persistence.EntityManager; -import javax.persistence.Id; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.Subgraph; - -import java.util.Set; - -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; - -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -/** - * @author Steve Ebersole - */ -public class BasicEntityGraphTests extends BaseEntityManagerFunctionalTestCase { - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { Entity1.class }; - } - - @Test - public void testBasicGraphBuilding() { - EntityManager em = getOrCreateEntityManager(); - EntityGraph graphRoot = em.createEntityGraph( Entity1.class ); - assertNull( graphRoot.getName() ); - assertEquals( 0, graphRoot.getAttributeNodes().size() ); - } - - @Test - public void testBasicSubgraphBuilding() { - EntityManager em = getOrCreateEntityManager(); - EntityGraph graphRoot = em.createEntityGraph( Entity1.class ); - Subgraph parentGraph = graphRoot.addSubgraph( "parent" ); - Subgraph childGraph = graphRoot.addSubgraph( "children" ); - - assertNull( graphRoot.getName() ); - assertEquals( 2, graphRoot.getAttributeNodes().size() ); - assertTrue( - graphRoot.getAttributeNodes().get( 0 ).getSubgraphs().containsValue( parentGraph ) - || graphRoot.getAttributeNodes().get( 0 ).getSubgraphs().containsValue( childGraph ) - ); - assertTrue( - graphRoot.getAttributeNodes().get( 1 ).getSubgraphs().containsValue( parentGraph ) - || graphRoot.getAttributeNodes().get( 1 ).getSubgraphs().containsValue( childGraph ) - ); - } - - @Test - @SuppressWarnings("unchecked") - public void testBasicGraphImmutability() { - EntityManager em = getOrCreateEntityManager(); - EntityGraph graphRoot = em.createEntityGraph( Entity1.class ); - graphRoot.addSubgraph( "parent" ); - graphRoot.addSubgraph( "children" ); - - em.getEntityManagerFactory().addNamedEntityGraph( "immutable", graphRoot ); - - graphRoot = (EntityGraph) em.getEntityGraph( "immutable" ); - - assertEquals( "immutable", graphRoot.getName() ); - assertEquals( 2, graphRoot.getAttributeNodes().size() ); - try { - graphRoot.addAttributeNodes( "parent" ); - fail( "Should have failed" ); - } - catch (IllegalStateException ignore) { - // expected outcome - } - - for ( AttributeNode attrNode : graphRoot.getAttributeNodes() ) { - assertEquals( 1, attrNode.getSubgraphs().size() ); - Subgraph subgraph = (Subgraph) attrNode.getSubgraphs().values().iterator().next(); - try { - graphRoot.addAttributeNodes( "parent" ); - fail( "Should have failed" ); - } - catch (IllegalStateException ignore) { - // expected outcome - } - } - } - - @Entity( name = "Entity1" ) - public static class Entity1 { - @Id - public Integer id; - public String name; - @ManyToOne - public Entity1 parent; - @OneToMany( mappedBy = "parent" ) - public Set children; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphNativeQueryTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphNativeQueryTest.java deleted file mode 100644 index 996e48a7a8..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphNativeQueryTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs; - -import java.util.HashSet; -import java.util.Set; -import javax.persistence.Entity; -import javax.persistence.EntityGraph; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; - -import org.hibernate.jpa.QueryHints; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; - -import org.hibernate.testing.TestForIssue; -import org.junit.Test; - -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.fail; - -/** - * @author Vlad Mihalcea - */ -@TestForIssue( jiraKey = "HHH-12476" ) -public class EntityGraphNativeQueryTest extends BaseEntityManagerFunctionalTestCase { - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { Foo.class, Bar.class, Baz.class }; - } - - @Override - protected void afterEntityManagerFactoryBuilt() { - doInJPA( this::entityManagerFactory, em -> { - 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 ); - } ); - } - - @Test - public void testQuery() { - Foo foo = doInJPA( this::entityManagerFactory, em -> { - EntityGraph fooGraph = em.createEntityGraph( Foo.class ); - fooGraph.addAttributeNodes( "bar", "baz" ); - - return em.createQuery( "select f from Foo f", Foo.class ) - .setHint( "javax.persistence.loadgraph", fooGraph ) - .getSingleResult(); - } ); - - assertNotNull( foo.bar ); - assertNotNull( foo.baz ); - } - - @Test - public void testNativeQueryLoadGraph() { - try { - doInJPA( this::entityManagerFactory, em -> { - EntityGraph fooGraph = em.createEntityGraph( Foo.class ); - fooGraph.addAttributeNodes( "bar", "baz" ); - - em.createNativeQuery( - "select " + - " f.id as id, " + - " f.bar_id as bar_id, " + - " f.baz_id as baz_id " + - "from Foo f", Foo.class ) - .setHint( QueryHints.HINT_LOADGRAPH, fooGraph ) - .getSingleResult(); - - fail("Should throw exception"); - } ); - } - catch (Exception e) { - assertEquals( "A native SQL query cannot use EntityGraphs", e.getMessage() ); - } - } - - @Test - public void testNativeQueryFetchGraph() { - try { - doInJPA( this::entityManagerFactory, em -> { - EntityGraph fooGraph = em.createEntityGraph( Foo.class ); - fooGraph.addAttributeNodes( "bar", "baz" ); - - em.createNativeQuery( - "select " + - " f.id as id, " + - " f.bar_id as bar_id, " + - " f.baz_id as baz_id " + - "from Foo f", Foo.class ) - .setHint( QueryHints.HINT_FETCHGRAPH, fooGraph ) - .getSingleResult(); - - fail("Should throw exception"); - } ); - } - catch (Exception e) { - assertEquals( "A native SQL query cannot use EntityGraphs", e.getMessage() ); - } - } - - @Entity(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(name = "Bar") - public static class Bar { - - @Id - @GeneratedValue - public Integer id; - - @OneToMany(mappedBy = "bar") - public Set foos = new HashSet<>(); - } - - @Entity(name = "Baz") - public static class Baz { - - @Id - @GeneratedValue - public Integer id; - - @OneToMany(mappedBy = "baz") - public Set foos = new HashSet<>(); - - } - -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphUsingFetchGraphTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphUsingFetchGraphTest.java deleted file mode 100644 index 0d4b457046..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphUsingFetchGraphTest.java +++ /dev/null @@ -1,337 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs; - -import javax.persistence.AttributeNode; -import javax.persistence.Entity; -import javax.persistence.EntityGraph; -import javax.persistence.EntityManager; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; -import javax.persistence.Subgraph; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.TypedQuery; -import javax.persistence.metamodel.Attribute; - -import java.util.Collection; -import java.util.Date; -import java.util.List; - -import org.hibernate.Hibernate; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; -import org.hibernate.metamodel.model.domain.EntityDomainType; -import org.hibernate.testing.TestForIssue; -import org.junit.Test; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -/** - * @author Baris Cubukcuoglu - */ -public class EntityGraphUsingFetchGraphTest extends BaseEntityManagerFunctionalTestCase { - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] {CustomerOrder.class, OrderPosition.class, Product.class, Address.class}; - } - - @Test - @TestForIssue( jiraKey = "HHH-9392") - public void fetchSubGraphFromSubgraph() { - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - - Address address = new Address(); - address.city = "TestCity"; - - CustomerOrder customerOrder = new CustomerOrder(); - customerOrder.shippingAddress = address; - - Product product = new Product(); - - OrderPosition orderPosition = new OrderPosition(); - orderPosition.product = product; - - customerOrder.orderPosition = orderPosition; - em.persist( address ); - em.persist( orderPosition ); - em.persist( product ); - em.persist( customerOrder ); - - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - - final EntityGraph entityGraph = em.createEntityGraph( CustomerOrder.class ); - //entityGraph.addAttributeNodes( "shippingAddress", "orderDate" ); - entityGraph.addAttributeNodes( "shippingAddress" ); - - final Subgraph orderProductsSubgraph = entityGraph.addSubgraph( "orderPosition" ); - //orderProductsSubgraph.addAttributeNodes( "amount" ); - - final Subgraph productSubgraph = orderProductsSubgraph.addSubgraph( "product" ); - //productSubgraph.addAttributeNodes( "productName" ); - - TypedQuery query = em.createQuery( - "SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class - ); - query.setHint( "javax.persistence.loadgraph", entityGraph ); - final List results = query.getResultList(); - - assertTrue( Hibernate.isInitialized( results ) ); - - em.getTransaction().commit(); - em.close(); - } - - @Test - @TestForIssue( jiraKey = "HHH-9392") - public void fetchAttributeNodeByStringFromSubgraph() { - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - - Address address = new Address(); - address.city = "TestCity"; - - CustomerOrder customerOrder = new CustomerOrder(); - customerOrder.shippingAddress = address; - - Product product = new Product(); - - OrderPosition orderPosition = new OrderPosition(); - orderPosition.product = product; - - customerOrder.orderPosition = orderPosition; - em.persist( address ); - em.persist( orderPosition ); - em.persist( product ); - em.persist( customerOrder ); - - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - - final EntityGraph entityGraph = em.createEntityGraph( CustomerOrder.class ); - entityGraph.addAttributeNodes( "shippingAddress", "orderDate" ); - entityGraph.addAttributeNodes( "shippingAddress" ); - - final Subgraph orderProductsSubgraph = entityGraph.addSubgraph( "orderPosition" ); - orderProductsSubgraph.addAttributeNodes( "amount" ); - orderProductsSubgraph.addAttributeNodes( "product" ); - - final Subgraph productSubgraph = orderProductsSubgraph.addSubgraph( "product" ); - productSubgraph.addAttributeNodes( "productName" ); - - TypedQuery query = em.createQuery( - "SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class - ); - query.setHint( "javax.persistence.loadgraph", entityGraph ); - final List results = query.getResultList(); - - assertEntityGraph( entityGraph ); - assertTrue( Hibernate.isInitialized( results ) ); - - em.getTransaction().commit(); - em.close(); - } - - @Test - @TestForIssue( jiraKey = "HHH-13233") - @SuppressWarnings({ "unchecked", "rawtypes" }) - public void fetchAttributeNodeByAttributeFromSubgraph() { - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - - Address address = new Address(); - address.city = "TestCity"; - - CustomerOrder customerOrder = new CustomerOrder(); - customerOrder.shippingAddress = address; - - Product product = new Product(); - - OrderPosition orderPosition = new OrderPosition(); - orderPosition.product = product; - - customerOrder.orderPosition = orderPosition; - em.persist( address ); - em.persist( orderPosition ); - em.persist( product ); - em.persist( customerOrder ); - - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - - final EntityGraph entityGraph = em.createEntityGraph( CustomerOrder.class ); - EntityDomainType customerOrderEntityType = - entityManagerFactory().getMetamodel().entity( CustomerOrder.class ); - entityGraph.addAttributeNodes( - (Attribute) customerOrderEntityType.getAttribute( "shippingAddress" ), - (Attribute) customerOrderEntityType.getAttribute( "orderDate" ) - ); - entityGraph.addAttributeNodes( (Attribute) customerOrderEntityType.getAttribute( "shippingAddress" ) ); - - final Subgraph orderProductsSubgraph = - entityGraph.addSubgraph( (Attribute) customerOrderEntityType.getAttribute( "orderPosition" ) ); - EntityDomainType positionEntityType = - entityManagerFactory().getMetamodel().entity( OrderPosition.class ); - orderProductsSubgraph.addAttributeNodes( (Attribute) positionEntityType.getAttribute( "amount" ) ); - orderProductsSubgraph.addAttributeNodes( (Attribute) positionEntityType.getAttribute( "product" ) ); - - final Subgraph productSubgraph = - orderProductsSubgraph.addSubgraph( (Attribute) positionEntityType.getAttribute( "product" ) ); - EntityDomainType productEntityType = entityManagerFactory().getMetamodel().entity( Product.class ); - productSubgraph.addAttributeNodes( (Attribute) productEntityType.getAttribute( "productName" ) ); - - TypedQuery query = em.createQuery( - "SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class - ); - query.setHint( "javax.persistence.loadgraph", entityGraph ); - final List results = query.getResultList(); - - assertEntityGraph( entityGraph ); - assertTrue( Hibernate.isInitialized( results ) ); - - em.getTransaction().commit(); - em.close(); - } - - @Test - @TestForIssue( jiraKey = "HHH-9392") - public void fetchUsingHql() { - // This test is here only for comparison with results from fetchAttributeNodeFromSubgraph. - // At the time this was written, the generated SQL from the HQL is the same as that generated with the - // query hint in fetchAttributeNodeFromSubgraph. I am leaving this here for future debugging purposes. - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - - Address address = new Address(); - address.city = "TestCity"; - - CustomerOrder customerOrder = new CustomerOrder(); - customerOrder.shippingAddress = address; - - Product product = new Product(); - - OrderPosition orderPosition = new OrderPosition(); - orderPosition.product = product; - - customerOrder.orderPosition = orderPosition; - em.persist( address ); - em.persist( orderPosition ); - em.persist( product ); - em.persist( customerOrder ); - - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - - TypedQuery query = em.createQuery( - "SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o left join fetch o.orderPosition pos left join fetch pos.product left join fetch o.shippingAddress", CustomerOrder.class - ); - final List results = query.getResultList(); - - assertTrue( Hibernate.isInitialized( results ) ); - - em.getTransaction().commit(); - em.close(); - } - - - /** - * Verify that entityGraph has expected state - * - * customerOrder - shippingAddress - * - orderDate - * - orderPosition - amount - * - product - productName - * - * @param entityGraph entityGraph - */ - private void assertEntityGraph(EntityGraph entityGraph) { - assertEquals(3, entityGraph.getAttributeNodes().size()); - for ( AttributeNode entityGraphAttributeNode : entityGraph.getAttributeNodes() ) { - if ( "orderPosition".equals( entityGraphAttributeNode.getAttributeName() ) ) { - Collection orderPositionGraph = entityGraphAttributeNode.getSubgraphs().values(); - assertEquals( 1, orderPositionGraph.size() ); - List> orderPositionAttributes = orderPositionGraph.iterator().next().getAttributeNodes(); - assertEquals( 2, orderPositionAttributes.size() ); - for ( AttributeNode orderPositionAttributeNode : orderPositionAttributes ) { - if ( "product".equals( orderPositionAttributeNode.getAttributeName() ) ) { - assertEquals( 1, orderPositionAttributeNode.getSubgraphs().size() ); - } else { - assertTrue( orderPositionAttributeNode.getSubgraphs().isEmpty() ); - } - } - } else { - assertTrue( entityGraphAttributeNode.getSubgraphs().isEmpty() ); - } - } - } - - @Entity - @Table(name = "customerOrder") - public static class CustomerOrder { - @Id - @GeneratedValue - public Long id; - - @OneToOne - public OrderPosition orderPosition; - - @Temporal(TemporalType.TIMESTAMP) - public Date orderDate; - - @OneToOne - public Address shippingAddress; - } - - @Entity - @Table(name = "address") - public static class Address { - @Id - @GeneratedValue - public Long id; - - public String city; - } - - @Entity - @Table(name = "orderPosition") - public static class OrderPosition { - @Id - @GeneratedValue - public Long id; - - public Integer amount; - - @ManyToOne - @JoinColumn(name = "product") - public Product product; - } - - @Entity - @Table(name = "product") - public static class Product { - @Id - @GeneratedValue - public Long id; - - public String productName; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphWithFetchAnnotationTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphWithFetchAnnotationTest.java deleted file mode 100644 index cfcc2176b4..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/EntityGraphWithFetchAnnotationTest.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs; - -import java.util.List; -import java.util.Map; -import javax.persistence.Entity; -import javax.persistence.EntityGraph; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.OneToMany; -import javax.persistence.Table; -import javax.persistence.criteria.CriteriaBuilder; -import javax.persistence.criteria.CriteriaQuery; - -import org.hibernate.annotations.Fetch; -import org.hibernate.annotations.FetchMode; -import org.hibernate.jpa.QueryHints; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; - -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.jdbc.SQLStatementInterceptor; -import org.hibernate.test.util.jdbc.PreparedStatementSpyConnectionProvider; -import org.junit.Test; - -import static org.hibernate.testing.transaction.TransactionUtil.doInJPA; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -/** - * @author Vlad Mihalcea - */ -public class EntityGraphWithFetchAnnotationTest - extends BaseEntityManagerFunctionalTestCase { - - private SQLStatementInterceptor sqlStatementInterceptor; - - @Override - protected void addConfigOptions(Map options) { - sqlStatementInterceptor = new SQLStatementInterceptor( options ); - } - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { - Order.class, - Product.class, - Tag.class, - }; - } - - @Test - @TestForIssue(jiraKey = "HHH-10485") - public void testWithoutEntityGraph() { - - doInJPA( this::entityManagerFactory, entityManager -> { - CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); - CriteriaQuery criteriaQuery = criteriaBuilder - .createQuery( Order.class ); - criteriaQuery.from( Order.class ); - - sqlStatementInterceptor.clear(); - - entityManager - .createQuery( criteriaQuery ) - .setFirstResult( 10 ) - .setMaxResults( 20 ) - .getResultList(); - - assertFalse( sqlStatementInterceptor.getSqlQueries().get( 0 ).toLowerCase().contains( "left outer join" ) ); - } ); - } - - @Test - @TestForIssue(jiraKey = "HHH-10485") - public void testWithEntityGraph() { - - doInJPA( this::entityManagerFactory, entityManager -> { - CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); - CriteriaQuery criteriaQuery = criteriaBuilder - .createQuery( Order.class ); - criteriaQuery.from( Order.class ); - - EntityGraph entityGraph = entityManager.createEntityGraph( Order.class ); - entityGraph.addAttributeNodes( "products" ); - - sqlStatementInterceptor.clear(); - - entityManager - .createQuery( criteriaQuery ) - .setFirstResult( 10 ) - .setMaxResults( 20 ) - .setHint( QueryHints.HINT_FETCHGRAPH, entityGraph ) - .getResultList(); - - assertTrue( sqlStatementInterceptor.getSqlQueries().get( 0 ).toLowerCase().contains( "left outer join" ) ); - } ); - } - - @Entity(name = "Order") - @Table(name = "orders") - public static class Order { - - @Id - @GeneratedValue - private long id; - - @OneToMany - @Fetch(FetchMode.SELECT) - private List products; - - @OneToMany - @Fetch(FetchMode.SELECT) - private List tags; - - public long getId() { - return this.id; - } - - public void setId(long id) { - this.id = id; - } - - public List getProducts() { - return this.products; - } - - public void setProducts(List products) { - this.products = products; - } - - public List getTags() { - return this.tags; - } - - public void setTags(List tags) { - this.tags = tags; - } - - } - - @Entity(name = "Product") - @Table(name = "products") - public static class Product { - - @Id - @GeneratedValue - private long id; - - private String name; - - public long getId() { - return this.id; - } - - public void setId(long id) { - this.id = id; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - } - - @Entity(name = "Tag") - @Table(name = "tags") - public static class Tag { - - @Id - @GeneratedValue - private long id; - - private String name; - - public long getId() { - return this.id; - } - - public void setId(long id) { - this.id = id; - } - - public String getName() { - return this.name; - } - - public void setName(String name) { - this.name = name; - } - - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/FetchWithRootGraphTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/FetchWithRootGraphTest.java deleted file mode 100644 index 928bc8b714..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/FetchWithRootGraphTest.java +++ /dev/null @@ -1,137 +0,0 @@ -package org.hibernate.jpa.test.graphs; - -import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.util.Collection; - -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.Id; -import javax.persistence.OneToOne; -import javax.persistence.Table; - -import org.hibernate.Hibernate; -import org.hibernate.graph.RootGraph; -import org.hibernate.testing.TestForIssue; -import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -public class FetchWithRootGraphTest extends BaseCoreFunctionalTestCase { - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[]{ - SimpleEntity.class, - EntityWithReference.class - }; - } - - @Before - public void before() { - doInHibernate( this::sessionFactory, s -> { - for ( long i = 0; i < 10; ++i ) { - SimpleEntity sim = new SimpleEntity( i, "Entity #" + i ); - EntityWithReference ref = new EntityWithReference( i, sim ); - s.save( sim ); - s.save( ref ); - } - } ); - } - - @After - public void after() { - doInHibernate( this::sessionFactory, s -> { - s.createQuery( "delete EntityWithReference" ).executeUpdate(); - s.createQuery( "delete SimpleEntity" ).executeUpdate(); - } ); - } - - @Test - @TestForIssue(jiraKey = "HHH-13312") - public void hhh13312Test() throws Exception { - doInHibernate( this::sessionFactory, s -> { - RootGraph g = s.createEntityGraph( EntityWithReference.class ); - g.addAttributeNode( "reference" ); - - EntityWithReference single = s.byId( EntityWithReference.class ) - .with( g ) - .load( 3L ); - - assertEquals( (long) single.getId(), 3L ); - assertTrue( Hibernate.isInitialized( single.getReference() ) ); - } ); - } - - @Entity(name = "SimpleEntity") - @Table(name = "SimpleEntity") - static class SimpleEntity { - - @Id - private Long id; - - private String text; - - public SimpleEntity() { - } - - public SimpleEntity(Long id, String text) { - this.id = id; - this.text = text; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } - } - - @Entity(name = "EntityWithReference") - @Table(name = "EntityWithReference") - static class EntityWithReference { - - @Id - private Long id; - - @OneToOne(fetch = FetchType.LAZY) - private SimpleEntity reference; - - public EntityWithReference() { - } - - public EntityWithReference(Long id, SimpleEntity ref) { - this.id = id; - this.reference = ref; - } - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public SimpleEntity getReference() { - return reference; - } - - public void setReference(SimpleEntity reference) { - this.reference = reference; - } - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/Bar.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/Bar.java deleted file mode 100644 index 9cf2830977..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/Bar.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs.inherited; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; - - -/** - * @author Oliver Breidenbach - */ -@Entity -public class Bar { - @Id @GeneratedValue - public long id; - -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/Foo.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/Foo.java deleted file mode 100644 index ada2ae2cf6..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/Foo.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs.inherited; - -import javax.persistence.Entity; - - -/** - * @author Oliver Breidenbach - */ -@Entity -public class Foo extends MappedSupperclass { - -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/Foo2.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/Foo2.java deleted file mode 100644 index 96d363bbba..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/Foo2.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs.inherited; - -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.OneToOne; - - -/** - * @author Oliver Breidenbach - */ -@Entity -public class Foo2 { - @Id @GeneratedValue - public long id; - - @OneToOne(fetch = FetchType.LAZY) - public Foo foo; - -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/InheritedEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/InheritedEntityGraphTest.java deleted file mode 100644 index f1d2f71533..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/InheritedEntityGraphTest.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs.inherited; - -import javax.persistence.EntityGraph; -import javax.persistence.EntityManager; -import javax.persistence.Subgraph; -import java.util.HashMap; -import java.util.Map; - -import org.hibernate.Hibernate; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; - -import org.junit.Test; - -import org.hibernate.testing.TestForIssue; - -import static org.junit.Assert.assertTrue; - -/** - * @author Oliver Breidenbach - */ -public class InheritedEntityGraphTest extends BaseEntityManagerFunctionalTestCase { - - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { Foo2.class, Foo.class, Bar.class }; - } - - @Test - @TestForIssue(jiraKey = "HHH-10261") - public void singleAttributeNodeInheritanceTest() { - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - - Bar bar = new Bar(); - em.persist(bar); - - Foo foo = new Foo(); - foo.bar = bar; - em.persist( foo ); - - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - - EntityGraph entityGraph = em.createEntityGraph( Foo.class ); - entityGraph.addSubgraph( "bar" ); - - Map properties = new HashMap(); - properties.put( "javax.persistence.loadgraph", entityGraph ); - - Foo result = em.find( Foo.class, foo.id, properties ); - - assertTrue( Hibernate.isInitialized( result ) ); - assertTrue( Hibernate.isInitialized( result.bar ) ); - - em.getTransaction().commit(); - em.close(); - } - - @Test - @TestForIssue(jiraKey = "HHH-10261") - public void collectionAttributeNodeInheritanceTest() { - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - - Bar bar = new Bar(); - em.persist(bar); - - Foo foo = new Foo(); - foo.bar = bar; - em.persist( foo ); - - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - - EntityGraph entityGraph = em.createEntityGraph( Foo.class ); - entityGraph.addSubgraph( "bars" ); - - Map properties = new HashMap(); - properties.put( "javax.persistence.loadgraph", entityGraph ); - - Foo result = em.find( Foo.class, foo.id, properties ); - - assertTrue( Hibernate.isInitialized( result ) ); - assertTrue( Hibernate.isInitialized( result.bars ) ); - - em.getTransaction().commit(); - em.close(); - } - - - @Test - @TestForIssue(jiraKey = "HHH-10261") - public void singleAttributeSubgraphInheritanceTest() { - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - - Bar bar = new Bar(); - em.persist(bar); - - Foo foo = new Foo(); - foo.bar = bar; - em.persist( foo ); - - Foo2 foo2 = new Foo2(); - foo2.foo = foo; - em.persist( foo2 ); - - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - - EntityGraph entityGraph = em.createEntityGraph( Foo2.class ); - Subgraph subgraphFoo = entityGraph.addSubgraph( "foo" ); - subgraphFoo.addSubgraph( "bar" ); - - Map properties = new HashMap(); - properties.put( "javax.persistence.loadgraph", entityGraph ); - - Foo2 result = em.find( Foo2.class, foo2.id, properties ); - - assertTrue( Hibernate.isInitialized( result ) ); - assertTrue( Hibernate.isInitialized( result.foo ) ); - assertTrue( Hibernate.isInitialized( result.foo.bar ) ); - - em.getTransaction().commit(); - em.close(); - } - - @Test - @TestForIssue(jiraKey = "HHH-10261") - public void collectionAttributeSubgraphInheritanceTest() { - EntityManager em = getOrCreateEntityManager(); - em.getTransaction().begin(); - - Bar bar = new Bar(); - em.persist(bar); - - Foo foo = new Foo(); - foo.bar = bar; - em.persist( foo ); - - Foo2 foo2 = new Foo2(); - foo2.foo = foo; - em.persist( foo2 ); - - em.getTransaction().commit(); - em.clear(); - - em.getTransaction().begin(); - - EntityGraph entityGraph = em.createEntityGraph( Foo2.class ); - Subgraph subgraphFoo = entityGraph.addSubgraph( "foo" ); - subgraphFoo.addSubgraph( "bars" ); - - Map properties = new HashMap(); - properties.put( "javax.persistence.loadgraph", entityGraph ); - - Foo2 result = em.find( Foo2.class, foo2.id, properties ); - - assertTrue( Hibernate.isInitialized( result ) ); - assertTrue( Hibernate.isInitialized( result.foo ) ); - assertTrue( Hibernate.isInitialized( result.foo.bars ) ); - - em.getTransaction().commit(); - em.close(); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/MappedSupperclass.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/MappedSupperclass.java deleted file mode 100644 index b57f8a4043..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/inherited/MappedSupperclass.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs.inherited; - -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.MappedSuperclass; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; -import java.util.HashSet; -import java.util.Set; - - -/** - * @author Oliver Breidenbach - */ -@MappedSuperclass -public class MappedSupperclass { - @Id @GeneratedValue - public long id; - - @OneToOne(fetch = FetchType.LAZY) - public Bar bar; - - @OneToMany - public Set bars = new HashSet(); - -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/AbstractNamedEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/AbstractNamedEntityGraphTest.java deleted file mode 100644 index 0cf45e28d2..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/AbstractNamedEntityGraphTest.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs.named.basic; - -import javax.persistence.EntityGraph; - -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; - -import org.junit.Test; - -import static junit.framework.Assert.assertNotNull; - -/** - * @author Steve Ebersole - */ -public abstract class AbstractNamedEntityGraphTest extends BaseEntityManagerFunctionalTestCase { - @Test - public void testIt() { - EntityGraph graph = getOrCreateEntityManager().getEntityGraph( "Person" ); - assertNotNull( graph ); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/BasicAnnNamedEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/BasicAnnNamedEntityGraphTest.java deleted file mode 100644 index a24444be0f..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/BasicAnnNamedEntityGraphTest.java +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs.named.basic; - -/** - * @author Strong Liu - */ -public class BasicAnnNamedEntityGraphTest extends AbstractNamedEntityGraphTest{ - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { Person.class }; - } - -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/BasicOrmNamedEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/BasicOrmNamedEntityGraphTest.java deleted file mode 100644 index 27d9061044..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/BasicOrmNamedEntityGraphTest.java +++ /dev/null @@ -1,17 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs.named.basic; - -/** - * @author Strong Liu - */ -public class BasicOrmNamedEntityGraphTest extends AbstractNamedEntityGraphTest{ - @Override - public String[] getEjb3DD() { - return new String[]{"org/hibernate/jpa/test/graphs/named/basic/orm.xml"}; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/Employee.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/Employee.java deleted file mode 100644 index b01dbe490c..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/Employee.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs.named.multiple; - -import javax.persistence.*; - -/** - * Employee - * - * @author Scott Marlow - */ -@Entity(name = "Employee") -@NamedEntityGraphs({ - @NamedEntityGraph( - name = "name_salary_graph", - includeAllAttributes = false, - attributeNodes = { - @NamedAttributeNode(value = "name"), - @NamedAttributeNode(value = "salary") - } - ), -}) -public class Employee { - @Id - public Long id; - - private String name; - private double salary; - - public Long getId() { - return id; - } - - public void setId(Long id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public double getSalary() { - return salary; - } - - public void setSalary(double salary) { - this.salary = salary; - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/NamedEntityGraphsTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/NamedEntityGraphsTest.java deleted file mode 100644 index 213fc4c743..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/NamedEntityGraphsTest.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs.named.multiple; - -import javax.persistence.AttributeNode; -import javax.persistence.EntityGraph; -import javax.persistence.EntityManager; - -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; - -import org.junit.Test; - -import java.util.List; - -import static junit.framework.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * @author Steve Ebersole - */ -public class NamedEntityGraphsTest extends BaseEntityManagerFunctionalTestCase { - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { Person.class, Employee.class }; - } - - @Test - public void testIt() { - EntityGraph graph = getOrCreateEntityManager().getEntityGraph( "abc" ); - assertNotNull( graph ); - graph = getOrCreateEntityManager().getEntityGraph( "xyz" ); - assertNotNull( graph ); - } - - @Test - public void testAttributeNodesAreAvailable() { - EntityManager em = getOrCreateEntityManager(); - EntityGraph graph = em.getEntityGraph( "name_salary_graph" ); - assertNotNull( graph ); - - List> list = graph.getAttributeNodes(); - assertNotNull( list ); - assertTrue("expected list.size() is two but actual list size is " + list.size(), 2 == list.size() ); - - AttributeNode attributeNode1 = list.get(0); - AttributeNode attributeNode2 = list.get(1); - assertNotNull( attributeNode1 ); - assertNotNull( attributeNode2 ); - - assertTrue( "node1 attribute name is expected to be either 'name' or 'salary' but actually is "+attributeNode1.getAttributeName(), - "name".equals(attributeNode1.getAttributeName()) || "salary".equals(attributeNode1.getAttributeName())); - - assertTrue( "node2 attribute name is expected to be either 'name' or 'salary' but actually is "+attributeNode2.getAttributeName(), - "name".equals(attributeNode2.getAttributeName()) || "salary".equals(attributeNode2.getAttributeName())); - } - -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/Person.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/Person.java deleted file mode 100644 index 69ce6ce79b..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/multiple/Person.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 . - */ -package org.hibernate.jpa.test.graphs.named.multiple; - -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.NamedEntityGraph; -import javax.persistence.NamedEntityGraphs; - -/** - * @author Steve Ebersole - */ -@Entity(name = "Person") -@NamedEntityGraphs({ - @NamedEntityGraph( name = "abc" ), - @NamedEntityGraph( name = "xyz" ) -}) -public class Person { - @Id - public Long id; -} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/SubgraphOrmNamedEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/SubgraphOrmNamedEntityGraphTest.java deleted file mode 100644 index 9c17628ecd..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/SubgraphOrmNamedEntityGraphTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package org.hibernate.jpa.test.graphs.named.subgraph; - -import java.util.List; -import javax.persistence.AttributeNode; -import javax.persistence.EntityGraph; -import javax.persistence.EntityManager; - -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; - -import org.hibernate.testing.TestForIssue; -import org.junit.Assert; -import org.junit.Test; - -import static org.junit.Assert.assertNotNull; - -public class SubgraphOrmNamedEntityGraphTest extends BaseEntityManagerFunctionalTestCase { - - @Override - public String[] getEjb3DD() { - return new String[]{"org/hibernate/jpa/test/graphs/named/subgraph/orm.xml"}; - } - - @Test - @TestForIssue( jiraKey = "HHH-10633" ) - public void testSubgraphsAreLoadededFromOrmXml() throws Exception { - EntityManager entityManager = getOrCreateEntityManager(); - List> lneg = entityManager.getEntityGraphs( Book.class ); - - assertNotNull( lneg ); - Assert.assertEquals(2, lneg.size()); - for (EntityGraph neg : lneg){ - if (neg.getName().equalsIgnoreCase( "full" )){ - assertNotNull( neg.getAttributeNodes() ); - for (AttributeNode n : neg.getAttributeNodes()){ - if (n.getAttributeName().equalsIgnoreCase( "authors" )) { - Assert.assertEquals(1, n.getSubgraphs().size()); - java.util.List> attributeNodes = n.getSubgraphs().get(Author.class).getAttributeNodes(); - assertNotNull("Subgraph attributes missing", attributeNodes); - Assert.assertEquals("Subgraph wrong number of attributes ", 3, attributeNodes.size()); - } - } - } - } - entityManager.close(); - } -} diff --git a/hibernate-core/src/test/java/org/hibernate/graph/EntityGraphFunctionalTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphFunctionalTests.java similarity index 79% rename from hibernate-core/src/test/java/org/hibernate/graph/EntityGraphFunctionalTests.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphFunctionalTests.java index 1a2a0ae332..2b63858119 100644 --- a/hibernate-core/src/test/java/org/hibernate/graph/EntityGraphFunctionalTests.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphFunctionalTests.java @@ -4,7 +4,7 @@ * 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.graph; +package org.hibernate.orm.test.entitygraph; import java.time.Instant; import java.util.ArrayList; @@ -22,28 +22,39 @@ import javax.persistence.ManyToOne; import javax.persistence.OneToMany; import javax.persistence.Table; -import org.hibernate.Hibernate; -import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; +import org.hibernate.graph.GraphParser; +import org.hibernate.graph.GraphSemantic; +import org.hibernate.graph.RootGraph; import org.hibernate.testing.TestForIssue; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; -import static org.hibernate.testing.transaction.TransactionUtil2.inTransaction; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hibernate.testing.hamcrest.InitializationCheckMatcher.isInitialized; +import static org.hibernate.testing.hamcrest.InitializationCheckMatcher.isNotInitialized; /** * @author Steve Ebersole */ -public class EntityGraphFunctionalTests extends BaseEntityManagerFunctionalTestCase { +@DomainModel( + annotatedClasses = { + EntityGraphFunctionalTests.User.class, + EntityGraphFunctionalTests.Issue.class, + EntityGraphFunctionalTests.Comment.class + } +) +@SessionFactory +public class EntityGraphFunctionalTests { @Test @TestForIssue( jiraKey = "HHH-13175") - public void testSubsequentSelectFromFind() { - inTransaction( - entityManagerFactory(), + void testSubsequentSelectFromFind(SessionFactoryScope scope) { + scope.inTransaction( session -> { final RootGraph graph = GraphParser.parse( Issue.class, "comments", session ); @@ -53,30 +64,19 @@ public class EntityGraphFunctionalTests extends BaseEntityManagerFunctionalTestC Collections.singletonMap( GraphSemantic.LOAD.getJpaHintName(), graph ) ); - assertTrue( Hibernate.isInitialized( issue ) ); - assertTrue( Hibernate.isInitialized( issue.getComments() ) ); - assertTrue( Hibernate.isInitialized( issue.getReporter() ) ); - assertTrue( Hibernate.isInitialized( issue.getAssignee() ) ); + assertThat( issue, isInitialized() ); + assertThat( issue.getComments(), isInitialized() ); + assertThat( issue.getReporter(), isInitialized() ); + assertThat( issue.getAssignee(), isInitialized() ); - assertFalse( Hibernate.isInitialized( issue.getAssignee().getAssignedIssues() ) ); + assertThat( issue.getAssignee().getAssignedIssues(), isNotInitialized() ); } ); } - @Override - protected Class[] getAnnotatedClasses() { - return new Class[] { User.class, Issue.class, Comment.class }; - } - - @Override - protected boolean createSchema() { - return true; - } - - @Before - public void prepareTestData() { - inTransaction( - entityManagerFactory(), + @BeforeEach + void prepareTestData(SessionFactoryScope scope) { + scope.inTransaction( session -> { final User wesley = new User( "Wesley", "farmboy" ); final User buttercup = new User( "Buttercup", "wishee" ); @@ -104,10 +104,9 @@ public class EntityGraphFunctionalTests extends BaseEntityManagerFunctionalTestC ); } - @After - public void cleanUpTestData() { - inTransaction( - entityManagerFactory(), + @AfterEach + void cleanUpTestData(SessionFactoryScope scope) { + scope.inTransaction( session -> { session.createQuery( "delete from Comment" ).executeUpdate(); session.createQuery( "delete from Issue" ).executeUpdate(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphNativeQueryTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphNativeQueryTest.java new file mode 100644 index 0000000000..1232399d2e --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphNativeQueryTest.java @@ -0,0 +1,170 @@ +/* + * 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 . + */ +package org.hibernate.orm.test.entitygraph; + +import java.util.HashSet; +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 org.hibernate.graph.GraphSemantic; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Vlad Mihalcea + */ +@DomainModel( + annotatedClasses = { + EntityGraphNativeQueryTest.Foo.class, + EntityGraphNativeQueryTest.Bar.class, + EntityGraphNativeQueryTest.Baz.class + } +) +@SessionFactory +@TestForIssue( jiraKey = "HHH-12476" ) +public class EntityGraphNativeQueryTest { + + @BeforeEach + void setUp(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Bar bar = new Bar(); + session.persist( bar ); + + Baz baz = new Baz(); + session.persist( baz ); + + Foo foo = new Foo(); + foo.bar = bar; + foo.baz = baz; + session.persist( foo ); + } + ); + } + + @Test + void testQuery(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph fooGraph = em.createEntityGraph( Foo.class ); + fooGraph.addAttributeNodes( "bar", "baz" ); + + Foo foo = em.createQuery( "select f from Foo f", Foo.class ) + .setHint( GraphSemantic.LOAD.getJpaHintName(), fooGraph ) + .getSingleResult(); + assertThat( foo.bar, notNullValue() ); + assertThat( foo.baz, notNullValue() ); + } + ); + } + + @Test + void testNativeQueryLoadGraph(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph fooGraph = em.createEntityGraph( Foo.class ); + fooGraph.addAttributeNodes( "bar", "baz" ); + + try { + em.createNativeQuery( + "select " + + " f.id as id, " + + " f.bar_id as bar_id, " + + " f.baz_id as baz_id " + + "from Foo f", Foo.class ) + .setHint( GraphSemantic.LOAD.getJpaHintName(), fooGraph ) + .getSingleResult(); + fail("Should throw exception"); + } catch (Exception e) { + assertThat( e.getMessage(), is( "A native SQL query cannot use EntityGraphs" ) ); + } + } + ); + } + + @Test + void testNativeQueryFetchGraph(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph fooGraph = em.createEntityGraph( Foo.class ); + fooGraph.addAttributeNodes( "bar", "baz" ); + + try { + em.createNativeQuery( + "select " + + " f.id as id, " + + " f.bar_id as bar_id, " + + " f.baz_id as baz_id " + + "from Foo f", Foo.class ) + .setHint( GraphSemantic.FETCH.getJpaHintName(), fooGraph ) + .getSingleResult(); + fail( "Should throw exception" ); + } catch (Exception e) { + assertThat( e.getMessage(), is( "A native SQL query cannot use EntityGraphs" ) ); + } + } + ); + } + + @Entity(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(name = "Bar") + public static class Bar { + + @Id + @GeneratedValue + public Integer id; + + @OneToMany(mappedBy = "bar") + public Set foos = new HashSet<>(); + } + + @Entity(name = "Baz") + public static class Baz { + + @Id + @GeneratedValue + public Integer id; + + @OneToMany(mappedBy = "baz") + public Set foos = new HashSet<>(); + + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphUsingFetchGraphTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphUsingFetchGraphTest.java new file mode 100644 index 0000000000..87a4d5bf63 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphUsingFetchGraphTest.java @@ -0,0 +1,336 @@ +/* + * 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 . + */ +package org.hibernate.orm.test.entitygraph; + +import java.util.Collection; +import java.util.Date; +import java.util.List; +import javax.persistence.AttributeNode; +import javax.persistence.Entity; +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToOne; +import javax.persistence.Subgraph; +import javax.persistence.Table; +import javax.persistence.Temporal; +import javax.persistence.TemporalType; +import javax.persistence.TypedQuery; +import javax.persistence.metamodel.Attribute; + +import org.hibernate.graph.GraphSemantic; +import org.hibernate.metamodel.model.domain.EntityDomainType; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hibernate.testing.hamcrest.CollectionMatchers.hasSize; +import static org.hibernate.testing.hamcrest.InitializationCheckMatcher.isInitialized; + +/** + * @author Baris Cubukcuoglu + */ +@DomainModel( + annotatedClasses = { + EntityGraphUsingFetchGraphTest.CustomerOrder.class, + EntityGraphUsingFetchGraphTest.OrderPosition.class, + EntityGraphUsingFetchGraphTest.Product.class, + EntityGraphUsingFetchGraphTest.Address.class + } +) +@SessionFactory +public class EntityGraphUsingFetchGraphTest { + + @Test + @TestForIssue( jiraKey = "HHH-9392") + void fetchSubGraphFromSubgraph(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Address address = new Address(); + address.city = "TestCity"; + + CustomerOrder customerOrder = new CustomerOrder(); + customerOrder.shippingAddress = address; + + Product product = new Product(); + + OrderPosition orderPosition = new OrderPosition(); + orderPosition.product = product; + + customerOrder.orderPosition = orderPosition; + session.persist( address ); + session.persist( orderPosition ); + session.persist( product ); + session.persist( customerOrder ); + } + ); + + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + final EntityGraph entityGraph = em.createEntityGraph( CustomerOrder.class ); + //entityGraph.addAttributeNodes( "shippingAddress", "orderDate" ); + entityGraph.addAttributeNodes( "shippingAddress" ); + + final Subgraph orderProductsSubgraph = entityGraph.addSubgraph( "orderPosition" ); + //orderProductsSubgraph.addAttributeNodes( "amount" ); + + final Subgraph productSubgraph = orderProductsSubgraph.addSubgraph( "product" ); + //productSubgraph.addAttributeNodes( "productName" ); + + TypedQuery query = em.createQuery( + "SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class + ); + query.setHint( GraphSemantic.LOAD.getJpaHintName(), entityGraph ); + final List results = query.getResultList(); + + assertThat( results, isInitialized() ); + } + ); + } + + @Test + @TestForIssue( jiraKey = "HHH-9392") + void fetchAttributeNodeByStringFromSubgraph(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Address address = new Address(); + address.city = "TestCity"; + + CustomerOrder customerOrder = new CustomerOrder(); + customerOrder.shippingAddress = address; + + Product product = new Product(); + + OrderPosition orderPosition = new OrderPosition(); + orderPosition.product = product; + + customerOrder.orderPosition = orderPosition; + session.persist( address ); + session.persist( orderPosition ); + session.persist( product ); + session.persist( customerOrder ); + } + ); + + scope.inTransaction( + session -> { + final EntityManager em = session.unwrap( EntityManager.class ); + final EntityGraph entityGraph = em.createEntityGraph( CustomerOrder.class ); + entityGraph.addAttributeNodes( "shippingAddress", "orderDate" ); + entityGraph.addAttributeNodes( "shippingAddress" ); + + final Subgraph orderProductsSubgraph = entityGraph.addSubgraph( "orderPosition" ); + orderProductsSubgraph.addAttributeNodes( "amount" ); + orderProductsSubgraph.addAttributeNodes( "product" ); + + final Subgraph productSubgraph = orderProductsSubgraph.addSubgraph( "product" ); + productSubgraph.addAttributeNodes( "productName" ); + + TypedQuery query = em.createQuery( + "SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class + ); + query.setHint( GraphSemantic.LOAD.getJpaHintName(), entityGraph ); + final List results = query.getResultList(); + + assertEntityGraph( entityGraph ); + assertThat( results, isInitialized() ); + } + ); + } + + @Test + @TestForIssue( jiraKey = "HHH-13233") + @SuppressWarnings({ "unchecked", "rawtypes" }) + void fetchAttributeNodeByAttributeFromSubgraph(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + Address address = new Address(); + address.city = "TestCity"; + + CustomerOrder customerOrder = new CustomerOrder(); + customerOrder.shippingAddress = address; + + Product product = new Product(); + + OrderPosition orderPosition = new OrderPosition(); + orderPosition.product = product; + + customerOrder.orderPosition = orderPosition; + session.persist( address ); + session.persist( orderPosition ); + session.persist( product ); + session.persist( customerOrder ); + } + ); + + scope.inTransaction( + session -> { + final EntityManager em = session.unwrap( EntityManager.class ); + final EntityGraph entityGraph = em.createEntityGraph( CustomerOrder.class ); + EntityDomainType customerOrderEntityType = + scope.getSessionFactory().getMetamodel().entity( CustomerOrder.class ); + entityGraph.addAttributeNodes( + (Attribute) customerOrderEntityType.getAttribute( "shippingAddress" ), + (Attribute) customerOrderEntityType.getAttribute( "orderDate" ) + ); + entityGraph.addAttributeNodes( (Attribute) customerOrderEntityType.getAttribute( "shippingAddress" ) ); + + final Subgraph orderProductsSubgraph = + entityGraph.addSubgraph( (Attribute) customerOrderEntityType.getAttribute( "orderPosition" ) ); + EntityDomainType positionEntityType = + scope.getSessionFactory().getMetamodel().entity( OrderPosition.class ); + orderProductsSubgraph.addAttributeNodes( (Attribute) positionEntityType.getAttribute( "amount" ) ); + orderProductsSubgraph.addAttributeNodes( (Attribute) positionEntityType.getAttribute( "product" ) ); + + final Subgraph productSubgraph = + orderProductsSubgraph.addSubgraph( (Attribute) positionEntityType.getAttribute( "product" ) ); + EntityDomainType productEntityType = scope.getSessionFactory().getMetamodel().entity( Product.class ); + productSubgraph.addAttributeNodes( (Attribute) productEntityType.getAttribute( "productName" ) ); + + TypedQuery query = em.createQuery( + "SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class + ); + query.setHint( GraphSemantic.LOAD.getJpaHintName(), entityGraph ); + final List results = query.getResultList(); + + assertEntityGraph( entityGraph ); + assertThat( results, isInitialized() ); + } + ); + } + + @Test + @TestForIssue( jiraKey = "HHH-9392") + void fetchUsingHql(SessionFactoryScope scope) { + // This test is here only for comparison with results from fetchAttributeNodeFromSubgraph. + // At the time this was written, the generated SQL from the HQL is the same as that generated with the + // query hint in fetchAttributeNodeFromSubgraph. I am leaving this here for future debugging purposes. + scope.inTransaction( + session -> { + Address address = new Address(); + address.city = "TestCity"; + + CustomerOrder customerOrder = new CustomerOrder(); + customerOrder.shippingAddress = address; + + Product product = new Product(); + + OrderPosition orderPosition = new OrderPosition(); + orderPosition.product = product; + + customerOrder.orderPosition = orderPosition; + session.persist( address ); + session.persist( orderPosition ); + session.persist( product ); + session.persist( customerOrder ); + } + ); + + scope.inTransaction( + session -> { + final EntityManager em = session.unwrap( EntityManager.class ); + TypedQuery query = em.createQuery( + "SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o left join fetch o.orderPosition pos left join fetch pos.product left join fetch o.shippingAddress", CustomerOrder.class + ); + final List results = query.getResultList(); + + assertThat( results, isInitialized() ); + } + ); + } + + /** + * Verify that entityGraph has expected state + * + * customerOrder - shippingAddress + * - orderDate + * - orderPosition - amount + * - product - productName + * + * @param entityGraph entityGraph + */ + private void assertEntityGraph(EntityGraph entityGraph) { + assertThat(entityGraph.getAttributeNodes(), hasSize( 3 ) ); + for ( AttributeNode entityGraphAttributeNode : entityGraph.getAttributeNodes() ) { + if ( "orderPosition".equals( entityGraphAttributeNode.getAttributeName() ) ) { + Collection orderPositionGraph = entityGraphAttributeNode.getSubgraphs().values(); + assertThat( orderPositionGraph, hasSize( 1 ) ); + List> orderPositionAttributes = orderPositionGraph.iterator().next().getAttributeNodes(); + assertThat( orderPositionAttributes, hasSize( 2 ) ); + for ( AttributeNode orderPositionAttributeNode : orderPositionAttributes ) { + if ( "product".equals( orderPositionAttributeNode.getAttributeName() ) ) { + assertThat( orderPositionAttributeNode.getSubgraphs().entrySet(), hasSize( 1 ) ); + } else { + assertThat( orderPositionAttributeNode.getSubgraphs().isEmpty(), is( true ) ); + } + } + } else { + assertThat( entityGraphAttributeNode.getSubgraphs().isEmpty(), is( true ) ); + } + } + } + + @Entity + @Table(name = "customerOrder") + public static class CustomerOrder { + @Id + @GeneratedValue + public Long id; + + @OneToOne + public OrderPosition orderPosition; + + @Temporal(TemporalType.TIMESTAMP) + public Date orderDate; + + @OneToOne + public Address shippingAddress; + } + + @Entity + @Table(name = "address") + public static class Address { + @Id + @GeneratedValue + public Long id; + + public String city; + } + + @Entity + @Table(name = "orderPosition") + public static class OrderPosition { + @Id + @GeneratedValue + public Long id; + + public Integer amount; + + @ManyToOne + @JoinColumn(name = "product") + public Product product; + } + + @Entity + @Table(name = "product") + public static class Product { + @Id + @GeneratedValue + public Long id; + + public String productName; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphWithFetchAnnotationTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphWithFetchAnnotationTest.java new file mode 100644 index 0000000000..834825a459 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/EntityGraphWithFetchAnnotationTest.java @@ -0,0 +1,201 @@ +/* + * 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 . + */ +package org.hibernate.orm.test.entitygraph; + +import java.util.List; +import javax.persistence.Entity; +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; + +import org.hibernate.annotations.Fetch; +import org.hibernate.annotations.FetchMode; +import org.hibernate.graph.GraphSemantic; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.jdbc.SQLStatementInspector; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * @author Vlad Mihalcea + */ +@DomainModel( + annotatedClasses = { + EntityGraphWithFetchAnnotationTest.Order.class, + EntityGraphWithFetchAnnotationTest.Product.class, + EntityGraphWithFetchAnnotationTest.Tag.class + } +) +@SessionFactory(statementInspectorClass = SQLStatementInspector.class) +public class EntityGraphWithFetchAnnotationTest { + + @Test + @TestForIssue(jiraKey = "HHH-10485") + void testWithoutEntityGraph(SessionFactoryScope scope) { + SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector(); + statementInspector.clear(); + + scope.inTransaction( + session -> { + EntityManager entityManager = session.unwrap( EntityManager.class ); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder + .createQuery( Order.class ); + criteriaQuery.from( Order.class ); + + entityManager + .createQuery( criteriaQuery ) + .setFirstResult( 10 ) + .setMaxResults( 20 ) + .getResultList(); + + statementInspector.assertExecutedCount( 1 ); + statementInspector.assertNumberOfOccurrenceInQuery( 0, "left outer join", 0 ); + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-10485") + void testWithEntityGraph(SessionFactoryScope scope) { + SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector(); + statementInspector.clear(); + + scope.inTransaction( + session -> { + EntityManager entityManager = session.unwrap( EntityManager.class ); + CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder(); + CriteriaQuery criteriaQuery = criteriaBuilder + .createQuery( Order.class ); + criteriaQuery.from( Order.class ); + + EntityGraph entityGraph = entityManager.createEntityGraph( Order.class ); + entityGraph.addAttributeNodes( "products" ); + + entityManager + .createQuery( criteriaQuery ) + .setFirstResult( 10 ) + .setMaxResults( 20 ) + .setHint( GraphSemantic.FETCH.getJpaHintName(), entityGraph ) + .getResultList(); + + statementInspector.assertExecutedCount( 1 ); + String sql = statementInspector.getSqlQueries().get( 0 ); + assertThat( sql, containsString( "left outer join" ) ); + } + ); + } + + @Entity(name = "Order") + @Table(name = "orders") + public static class Order { + + @Id + @GeneratedValue + private long id; + + @OneToMany + @Fetch(FetchMode.SELECT) + private List products; + + @OneToMany + @Fetch(FetchMode.SELECT) + private List tags; + + public long getId() { + return this.id; + } + + public void setId(long id) { + this.id = id; + } + + public List getProducts() { + return this.products; + } + + public void setProducts(List products) { + this.products = products; + } + + public List getTags() { + return this.tags; + } + + public void setTags(List tags) { + this.tags = tags; + } + + } + + @Entity(name = "Product") + @Table(name = "products") + public static class Product { + + @Id + @GeneratedValue + private long id; + + private String name; + + public long getId() { + return this.id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + } + + @Entity(name = "Tag") + @Table(name = "tags") + public static class Tag { + + @Id + @GeneratedValue + private long id; + + private String name; + + public long getId() { + return this.id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/FetchWithRootGraphTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/FetchWithRootGraphTest.java new file mode 100644 index 0000000000..e0bceef924 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/FetchWithRootGraphTest.java @@ -0,0 +1,142 @@ +package org.hibernate.orm.test.entitygraph; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.OneToOne; +import javax.persistence.Table; + +import org.hibernate.graph.RootGraph; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hibernate.testing.hamcrest.InitializationCheckMatcher.isInitialized; + +@DomainModel( + annotatedClasses = { + FetchWithRootGraphTest.SimpleEntity.class, + FetchWithRootGraphTest.EntityWithReference.class + } +) +@SessionFactory +public class FetchWithRootGraphTest { + + @BeforeEach + void before(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + for ( long i = 0; i < 10; ++i ) { + SimpleEntity sim = new SimpleEntity( i, "Entity #" + i ); + EntityWithReference ref = new EntityWithReference( i, sim ); + session.save( sim ); + session.save( ref ); + } + } + ); + } + + @AfterEach + void after(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "delete EntityWithReference" ).executeUpdate(); + session.createQuery( "delete SimpleEntity" ).executeUpdate(); + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-13312") + void hhh13312Test(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + RootGraph g = session.createEntityGraph( EntityWithReference.class ); + g.addAttributeNode( "reference" ); + + EntityWithReference single = session.byId( EntityWithReference.class ) + .with( g ) + .load( 3L ); + + assertThat( single.getId(), is( 3L ) ); + assertThat( single.getReference(), isInitialized() ); + } + ); + } + + @Entity(name = "SimpleEntity") + @Table(name = "SimpleEntity") + static class SimpleEntity { + + @Id + private Long id; + + private String text; + + public SimpleEntity() { + } + + public SimpleEntity(Long id, String text) { + this.id = id; + this.text = text; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + } + + @Entity(name = "EntityWithReference") + @Table(name = "EntityWithReference") + static class EntityWithReference { + + @Id + private Long id; + + @OneToOne(fetch = FetchType.LAZY) + private SimpleEntity reference; + + public EntityWithReference() { + } + + public EntityWithReference(Long id, SimpleEntity ref) { + this.id = id; + this.reference = ref; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public SimpleEntity getReference() { + return reference; + } + + public void setReference(SimpleEntity reference) { + this.reference = reference; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/InheritedEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/InheritedEntityGraphTest.java new file mode 100644 index 0000000000..0826413adc --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/InheritedEntityGraphTest.java @@ -0,0 +1,245 @@ +/* + * 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 . + */ +package org.hibernate.orm.test.entitygraph; + +import java.util.Collections; +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.MappedSuperclass; +import javax.persistence.OneToMany; +import javax.persistence.OneToOne; +import javax.persistence.Subgraph; + +import org.hibernate.graph.GraphSemantic; +import org.hibernate.internal.util.MutableLong; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hibernate.testing.hamcrest.InitializationCheckMatcher.isInitialized; + +/** + * @author Oliver Breidenbach + */ +@DomainModel( + annotatedClasses = { + InheritedEntityGraphTest.Foo2.class, + InheritedEntityGraphTest.Foo.class, + InheritedEntityGraphTest.Bar.class + } +) +@SessionFactory +public class InheritedEntityGraphTest { + + @Test + @TestForIssue(jiraKey = "HHH-10261") + void singleAttributeNodeInheritanceTest(SessionFactoryScope scope) { + + MutableLong fooId = new MutableLong(); + + scope.inTransaction( + session -> { + Bar bar = new Bar(); + session.persist(bar); + + Foo foo = new Foo(); + foo.bar = bar; + session.persist( foo ); + + fooId.set( foo.id ); + } + ); + + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph entityGraph = em.createEntityGraph( Foo.class ); + entityGraph.addSubgraph( "bar" ); + + Map properties = Collections.singletonMap( + GraphSemantic.LOAD.getJpaHintName(), entityGraph + ); + + Foo result = em.find( Foo.class, fooId.get(), properties ); + + assertThat( result, isInitialized() ); + assertThat( result.bar, isInitialized() ); + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-10261") + void collectionAttributeNodeInheritanceTest(SessionFactoryScope scope) { + + MutableLong fooId = new MutableLong(); + + scope.inTransaction( + session -> { + Bar bar = new Bar(); + session.persist(bar); + + Foo foo = new Foo(); + foo.bar = bar; + session.persist( foo ); + + fooId.set( foo.id ); + } + ); + + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph entityGraph = em.createEntityGraph( Foo.class ); + entityGraph.addSubgraph( "bars" ); + + Map properties = Collections.singletonMap( + GraphSemantic.LOAD.getJpaHintName(), entityGraph + ); + + Foo result = em.find( Foo.class, fooId.get(), properties ); + + assertThat( result, isInitialized() ); + assertThat( result.bars, isInitialized() ); + } + ); + } + + + @Test + @TestForIssue(jiraKey = "HHH-10261") + void singleAttributeSubgraphInheritanceTest(SessionFactoryScope scope) { + + MutableLong foo2Id = new MutableLong(); + + scope.inTransaction( + session -> { + Bar bar = new Bar(); + session.persist(bar); + + Foo foo = new Foo(); + foo.bar = bar; + session.persist( foo ); + + Foo2 foo2 = new Foo2(); + foo2.foo = foo; + session.persist( foo2 ); + + foo2Id.set( foo2.id ); + } + ); + + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph entityGraph = em.createEntityGraph( Foo2.class ); + Subgraph subgraphFoo = entityGraph.addSubgraph( "foo" ); + subgraphFoo.addSubgraph( "bar" ); + + Map properties = Collections.singletonMap( + GraphSemantic.LOAD.getJpaHintName(), entityGraph + ); + + Foo2 result = em.find( Foo2.class, foo2Id.get(), properties ); + + assertThat( result, isInitialized() ); + assertThat( result.foo, isInitialized() ); + assertThat( result.foo.bar, isInitialized() ); + } + ); + } + + @Test + @TestForIssue(jiraKey = "HHH-10261") + void collectionAttributeSubgraphInheritanceTest(SessionFactoryScope scope) { + + MutableLong foo2Id = new MutableLong(); + + scope.inTransaction( + session -> { + Bar bar = new Bar(); + session.persist(bar); + + Foo foo = new Foo(); + foo.bar = bar; + session.persist( foo ); + + Foo2 foo2 = new Foo2(); + foo2.foo = foo; + session.persist( foo2 ); + + foo2Id.set( foo2.id ); + } + ); + + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph entityGraph = em.createEntityGraph( Foo2.class ); + Subgraph subgraphFoo = entityGraph.addSubgraph( "foo" ); + subgraphFoo.addSubgraph( "bars" ); + + Map properties = Collections.singletonMap( + GraphSemantic.LOAD.getJpaHintName(), entityGraph + ); + + Foo2 result = em.find( Foo2.class, foo2Id.get(), properties ); + + assertThat( result, isInitialized() ); + assertThat( result.foo, isInitialized() ); + assertThat( result.foo.bars, isInitialized() ); + } + ); + } + + @MappedSuperclass + public static class MappedSupperclass { + @Id + @GeneratedValue + public long id; + + @OneToOne(fetch = FetchType.LAZY) + public Bar bar; + + @OneToMany + public Set bars = new HashSet(); + + } + + @Entity + public static class Bar { + @Id @GeneratedValue + public long id; + + } + + @Entity + public static class Foo extends MappedSupperclass { + + } + + @Entity + public static class Foo2 { + @Id @GeneratedValue + public long id; + + @OneToOne(fetch = FetchType.LAZY) + public Foo foo; + + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/LoadAndFetchGraphTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/LoadAndFetchGraphTest.java new file mode 100644 index 0000000000..dc84124f27 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/LoadAndFetchGraphTest.java @@ -0,0 +1,542 @@ +package org.hibernate.orm.test.entitygraph; + +import java.util.ArrayList; +import java.util.List; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; +import javax.persistence.FetchType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; +import javax.persistence.TypedQuery; + +import org.hibernate.graph.GraphSemantic; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.jdbc.SQLStatementInspector; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.hasSize; +import static org.hibernate.testing.hamcrest.InitializationCheckMatcher.isInitialized; +import static org.hibernate.testing.hamcrest.InitializationCheckMatcher.isNotInitialized; + +/** + * @author Andrea Boriero + * @author Nathan Xu + */ +@DomainModel( + annotatedClasses = { + LoadAndFetchGraphTest.AEntity.class, + LoadAndFetchGraphTest.BEntity.class, + LoadAndFetchGraphTest.CEntity.class, + LoadAndFetchGraphTest.DEntity.class, + LoadAndFetchGraphTest.EEntity.class + } +) +@SessionFactory(statementInspectorClass = SQLStatementInspector.class) +@TestForIssue(jiraKey = "HHH-14097") +public class LoadAndFetchGraphTest { + + @BeforeEach + void setUp(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager entityManager = session.unwrap( EntityManager.class ); + AEntity a1 = new AEntity(); + a1.setId( 1 ); + a1.setLabel( "A1" ); + + AEntity a2 = new AEntity(); + a2.setId( 2 ); + a2.setLabel( "A2" ); + + entityManager.persist( a1 ); + entityManager.persist( a2 ); + + BEntity b1 = new BEntity(); + b1.setId( 1 ); + b1.setLabel( "B1" ); + + BEntity b2 = new BEntity(); + b2.setId( 2 ); + b2.setLabel( "B2" ); + + entityManager.persist( b1 ); + entityManager.persist( b2 ); + + EEntity e1 = new EEntity(); + e1.setId( 1 ); + e1.setLabel( "E1" ); + + EEntity e2 = new EEntity(); + e2.setId( 2 ); + e2.setLabel( "E2" ); + + EEntity e3 = new EEntity(); + e3.setId( 3 ); + e3.setLabel( "E3" ); + + EEntity e4 = new EEntity(); + e4.setId( 4 ); + e4.setLabel( "E4" ); + + entityManager.persist( e1 ); + entityManager.persist( e2 ); + entityManager.persist( e3 ); + entityManager.persist( e4 ); + + DEntity d1 = new DEntity(); + d1.setId( 1 ); + d1.setLabel( "D1" ); + d1.setE( e1 ); + + DEntity d2 = new DEntity(); + d2.setId( 2 ); + d2.setLabel( "D2" ); + d2.setE( e2 ); + + CEntity c1 = new CEntity(); + c1.setId( 1 ); + c1.setLabel( "C1" ); + c1.setA( a1 ); + c1.setB( b1 ); + c1.addD( d1 ); + c1.addD( d2 ); + + entityManager.persist( c1 ); + + DEntity d3 = new DEntity(); + d3.setId( 3 ); + d3.setLabel( "D3" ); + d3.setE( e3 ); + + DEntity d4 = new DEntity(); + d4.setId( 4 ); + d4.setLabel( "D4" ); + d4.setE( e4 ); + + CEntity c2 = new CEntity(); + c2.setId( 2 ); + c2.setLabel( "C2" ); + c2.setA( a2 ); + c2.setB( b2 ); + c2.addD( d3 ); + c2.addD( d4 ); + + entityManager.persist( c2 ); + + CEntity c3 = new CEntity(); + c3.setId( 3 ); + c3.setLabel( "C3" ); + + entityManager.persist( c3 ); + + c1.setC( c2 ); + c2.setC( c3 ); + + int id = 5; + for ( int i = 0; i < 10; i++ ) { + DEntity dn = new DEntity(); + dn.setId( id++ ); + dn.setLabel( "label" ); + dn.setE( e3 ); + entityManager.persist( dn ); + } + } + ); + } + + @AfterEach + void tearDown(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + session.createQuery( "delete from DEntity" ).executeUpdate(); + session.createQuery( "delete from EEntity" ).executeUpdate(); + session.createQuery( "delete from CEntity" ).executeUpdate(); + session.createQuery( "delete from AEntity" ).executeUpdate(); + session.createQuery( "delete from BEntity" ).executeUpdate(); + } + ); + } + + @Test + void testQueryById(SessionFactoryScope scope) { + SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector(); + statementInspector.clear(); + scope.inTransaction( + session -> { + EntityManager entityManager = session.unwrap( EntityManager.class ); + TypedQuery query = entityManager.createQuery( + "select c from CEntity as c where c.id = :cid ", + CEntity.class + ); + query.setParameter( "cid", 1 ); + CEntity cEntity = query.getSingleResult(); + + assertThat( cEntity.getA(), isNotInitialized() ); + assertThat( cEntity.getB(), isNotInitialized() ); + assertThat( cEntity.getC(), isNotInitialized() ); + assertThat( cEntity.getDList(), isNotInitialized() ); + + assertThat( statementInspector.getSqlQueries(), hasSize( 1 ) ); + } + ); + } + + @Test + void testQueryByIdWithLoadGraph(SessionFactoryScope scope) { + SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector(); + statementInspector.clear(); + scope.inTransaction( + session -> { + EntityManager entityManager = session.unwrap( EntityManager.class ); + EntityGraph entityGraph = entityManager.createEntityGraph( CEntity.class ); + entityGraph.addAttributeNodes( "a", "b" ); + entityGraph.addSubgraph( "dList" ).addAttributeNodes( "e" ); + + TypedQuery query = entityManager.createQuery( + "select c from CEntity as c where c.id = :cid ", + CEntity.class + ); + query.setHint( GraphSemantic.LOAD.getJpaHintName(), entityGraph ); + query.setParameter( "cid", 1 ); + + CEntity cEntity = query.getSingleResult(); + + assertThat( cEntity.getA(), isInitialized() ); + assertThat( cEntity.getB(), isInitialized() ); + assertThat( cEntity.getC(), isNotInitialized() ); + assertThat( cEntity.getDList(), isInitialized() ); + cEntity.getDList().forEach( dEntity -> assertThat( dEntity.getE(), isInitialized() ) ); + + assertThat( statementInspector.getSqlQueries(), hasSize( 1 ) ); + } + ); + } + + @Test + void testQueryByIdWithFetchGraph(SessionFactoryScope scope) { + SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector(); + statementInspector.clear(); + scope.inTransaction( + session -> { + EntityManager entityManager = session.unwrap( EntityManager.class ); + EntityGraph entityGraph = entityManager.createEntityGraph( CEntity.class ); + entityGraph.addAttributeNodes( "a", "b" ); + entityGraph.addSubgraph( "dList" ).addAttributeNodes( "e" ); + + TypedQuery query = entityManager.createQuery( + "select c from CEntity as c where c.id = :cid ", + CEntity.class + ); + query.setHint( GraphSemantic.FETCH.getJpaHintName(), entityGraph ); + query.setParameter( "cid", 1 ); + + CEntity cEntity = query.getSingleResult(); + assertThat( cEntity.getA(), isInitialized() ); + assertThat( cEntity.getB(), isInitialized() ); + assertThat( cEntity.getC(), isNotInitialized() ); + assertThat( cEntity.getDList(), isInitialized() ); + cEntity.getDList().forEach( dEntity -> assertThat( dEntity.getE(), isInitialized() ) ); + + assertThat( statementInspector.getSqlQueries(), hasSize( 1 ) ); + } + ); + } + + @Test + void testQueryByIdWithFetchGraph2(SessionFactoryScope scope) { + SQLStatementInspector statementInspector = (SQLStatementInspector) scope.getStatementInspector(); + statementInspector.clear(); + scope.inTransaction( + session -> { + EntityManager entityManager = session.unwrap( EntityManager.class ); + EntityGraph entityGraph = entityManager.createEntityGraph( CEntity.class ); + entityGraph.addSubgraph( "c" ).addAttributeNodes( "a" ); + + TypedQuery query = entityManager.createQuery( + "select c from CEntity as c where c.id = :cid ", + CEntity.class + ); + query.setHint( GraphSemantic.FETCH.getJpaHintName(), entityGraph ); + query.setParameter( "cid", 1 ); + + CEntity cEntity = query.getSingleResult(); + assertThat( cEntity.getC(), isInitialized() ); + assertThat( cEntity.getC().getA(), isInitialized() ); + assertThat( cEntity.getC().getC(), isNotInitialized() ); + + assertThat( statementInspector.getSqlQueries(), hasSize( 1 ) ); + } + ); + } + + @Entity(name = "AEntity") + @Table(name = "A") + public static class AEntity { + + @Id + private Integer id; + + private String label; + + @OneToMany( + fetch = FetchType.LAZY, + mappedBy = "a", + cascade = CascadeType.ALL, + orphanRemoval = true + ) + private List cList = new ArrayList<>(); + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public List getCList() { + return cList; + } + + public void setCList(List cList) { + this.cList = cList; + } + } + + @Entity(name = "BEntity") + @Table(name = "B") + public static class BEntity { + + @Id + private Integer id; + + private String label; + + @OneToMany( + fetch = FetchType.LAZY, + mappedBy = "b", + cascade = CascadeType.ALL, + orphanRemoval = true + ) + private List cList = new ArrayList<>(); + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public List getCList() { + return cList; + } + + public void setCList(List cList) { + this.cList = cList; + } + } + + @Entity(name = "CEntity") + @Table(name = "C") + public static class CEntity { + + @Id + private Integer id; + + private String label; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "A_ID") + private AEntity a; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "B_ID") + private BEntity b; + + @ManyToOne(fetch = FetchType.LAZY) + private CEntity c; + + @OneToMany( + fetch = FetchType.LAZY, + mappedBy = "c", + cascade = CascadeType.ALL, + orphanRemoval = true + ) + private List dList = new ArrayList<>(); + + public void addD(DEntity d) { + dList.add( d ); + d.setC( this ); + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public AEntity getA() { + return a; + } + + public void setA(AEntity a) { + this.a = a; + } + + public BEntity getB() { + return b; + } + + public void setB(BEntity b) { + this.b = b; + } + + public CEntity getC() { + return c; + } + + public void setC(CEntity c) { + this.c = c; + } + + public List getDList() { + return dList; + } + + public void setDList(List dList) { + this.dList = dList; + } + } + + @Entity(name = "DEntity") + @Table(name = "D") + public static class DEntity { + + @Id + private Integer id; + + private String label; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "C_ID") + private CEntity c; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "E_ID") + private EEntity e; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public CEntity getC() { + return c; + } + + public void setC(CEntity c) { + this.c = c; + } + + public EEntity getE() { + return e; + } + + public void setE(EEntity e) { + this.e = e; + } + } + + @Entity(name = "EEntity") + @Table(name = "E") + public static class EEntity { + + @Id + private Integer id; + + private String label; + + @OneToMany( + fetch = FetchType.LAZY, + mappedBy = "e", + cascade = CascadeType.ALL, + orphanRemoval = true + ) + private List dList = new ArrayList<>(); + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public List getDList() { + return dList; + } + + public void setDList(List dList) { + this.dList = dList; + } + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/entitygraph/CriteriaEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/CriteriaEntityGraphTest.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/entitygraph/CriteriaEntityGraphTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/CriteriaEntityGraphTest.java index 04664e8123..8b08536935 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/criteria/entitygraph/CriteriaEntityGraphTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/CriteriaEntityGraphTest.java @@ -4,7 +4,7 @@ * 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.orm.test.query.criteria.entitygraph; +package org.hibernate.orm.test.entitygraph.ast; import java.util.HashMap; import java.util.Map; @@ -341,8 +341,6 @@ public class CriteriaEntityGraphTest implements SessionFactoryScopeAware { SessionImplementor session) { final LoadQueryInfluencers loadQueryInfluencers = new LoadQueryInfluencers( session.getSessionFactory() ); - final EffectiveEntityGraph effectiveEntityGraph = loadQueryInfluencers.getEffectiveEntityGraph(); - effectiveEntityGraph.applyGraph( entityGraph, mode ); final CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder(); CriteriaQuery criteriaQuery = criteriaBuilder.createQuery( entityType ); @@ -350,6 +348,7 @@ public class CriteriaEntityGraphTest implements SessionFactoryScopeAware { final QueryImplementor query = session.createQuery( criteriaQuery ); final HqlQueryImplementor hqlQuery = (HqlQueryImplementor) query; + hqlQuery.applyGraph( entityGraph, mode ); final SqmSelectStatement sqmStatement = (SqmSelectStatement) hqlQuery.getSqmStatement(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/EntityGraphLoadPlanBuilderTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/EntityGraphLoadPlanBuilderTest.java similarity index 99% rename from hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/EntityGraphLoadPlanBuilderTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/EntityGraphLoadPlanBuilderTest.java index 61a0cf4197..f15e1fd1db 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/EntityGraphLoadPlanBuilderTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/EntityGraphLoadPlanBuilderTest.java @@ -4,7 +4,7 @@ * 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.orm.test.loading.entitygraph; +package org.hibernate.orm.test.entitygraph.ast; import java.util.HashMap; import java.util.Map; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/entitygraph/HqlEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/HqlEntityGraphTest.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/entitygraph/HqlEntityGraphTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/HqlEntityGraphTest.java index ea62e226dc..3aebbac768 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/query/hql/entitygraph/HqlEntityGraphTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/HqlEntityGraphTest.java @@ -4,7 +4,7 @@ * 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.orm.test.query.hql.entitygraph; +package org.hibernate.orm.test.entitygraph.ast; import java.util.HashMap; import java.util.Map; @@ -20,7 +20,6 @@ import javax.persistence.Id; import javax.persistence.ManyToOne; import javax.persistence.OneToMany; -import org.hibernate.engine.spi.EffectiveEntityGraph; import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.graph.GraphSemantic; @@ -340,14 +339,13 @@ public class HqlEntityGraphTest implements SessionFactoryScopeAware { SessionImplementor session) { final LoadQueryInfluencers loadQueryInfluencers = new LoadQueryInfluencers( session.getSessionFactory() ); - final EffectiveEntityGraph effectiveEntityGraph = loadQueryInfluencers.getEffectiveEntityGraph(); - effectiveEntityGraph.applyGraph( entityGraph, mode ); final QueryImplementor query = session.createQuery( hql, entityType ); final HqlQueryImplementor hqlQuery = (HqlQueryImplementor) query; + hqlQuery.applyGraph( entityGraph, mode ); final SqmSelectStatement sqmStatement = (SqmSelectStatement) hqlQuery.getSqmStatement(); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/plan/LoadPlanBuilderTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/LoadPlanBuilderTest.java similarity index 99% rename from hibernate-core/src/test/java/org/hibernate/orm/test/loading/plan/LoadPlanBuilderTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/LoadPlanBuilderTest.java index 66932ba953..c473a53f1b 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/plan/LoadPlanBuilderTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/ast/LoadPlanBuilderTest.java @@ -4,7 +4,7 @@ * 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.orm.test.loading.plan; +package org.hibernate.orm.test.entitygraph.ast; import java.util.List; import javax.persistence.CascadeType; diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/mappedbyid/LoadGraphFindByIdTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/mappedbyid/LoadGraphFindByIdTest.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/mappedbyid/LoadGraphFindByIdTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/mappedbyid/LoadGraphFindByIdTest.java index cec8e85db3..15356cf4fb 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/mappedbyid/LoadGraphFindByIdTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/mappedbyid/LoadGraphFindByIdTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.jpa.test.graphs.mappedbyid; +package org.hibernate.orm.test.entitygraph.mappedbyid; import java.util.HashMap; import java.util.Map; @@ -23,7 +23,6 @@ import javax.persistence.criteria.Root; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; -import org.hibernate.testing.FailureExpected; import org.hibernate.testing.TestForIssue; import org.junit.Assert; import org.junit.FixMethodOrder; @@ -60,7 +59,6 @@ public class LoadGraphFindByIdTest extends BaseEntityManagerFunctionalTestCase { @Test @TestForIssue(jiraKey = "HHH-10842") - @FailureExpected( jiraKey = "HHH-10842" ) public void findByPrimaryKeyWithId() { doInJPA( this::entityManagerFactory, em -> { User result = em.find( User.class, 1L, createProperties( em ) ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/BasicAnnNamedEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/BasicAnnNamedEntityGraphTest.java new file mode 100644 index 0000000000..a9cd673793 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/BasicAnnNamedEntityGraphTest.java @@ -0,0 +1,40 @@ +/* + * 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 . + */ +package org.hibernate.orm.test.entitygraph.named.basic; + +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * @author Strong Liu + */ +@DomainModel( + annotatedClasses = Person.class +) +@SessionFactory +public class BasicAnnNamedEntityGraphTest { + + @Test + void testIt(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph graph = em.getEntityGraph( "Person" ); + assertThat( graph, notNullValue() ); + } + ); + } + +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/BasicOrmNamedEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/BasicOrmNamedEntityGraphTest.java new file mode 100644 index 0000000000..ce7bcc429a --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/BasicOrmNamedEntityGraphTest.java @@ -0,0 +1,39 @@ +/* + * 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 . + */ +package org.hibernate.orm.test.entitygraph.named.basic; + +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; + +/** + * @author Strong Liu + */ +@DomainModel( + xmlMappings = "org/hibernate/orm/test/entitygraph/named/basic/orm.xml" +) +@SessionFactory +public class BasicOrmNamedEntityGraphTest { + + @Test + void testIt(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph graph = em.getEntityGraph( "Person" ); + assertThat( graph, notNullValue() ); + } + ); + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/Person.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/Person.java similarity index 88% rename from hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/Person.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/Person.java index 2719b5d0f4..d0df647b3f 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/basic/Person.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/Person.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.jpa.test.graphs.named.basic; +package org.hibernate.orm.test.entitygraph.named.basic; import javax.persistence.Entity; import javax.persistence.Id; diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/graphs/named/basic/orm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/orm.xml similarity index 90% rename from hibernate-core/src/test/resources/org/hibernate/jpa/test/graphs/named/basic/orm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/orm.xml index 15b1caad35..8cbb7e7949 100644 --- a/hibernate-core/src/test/resources/org/hibernate/jpa/test/graphs/named/basic/orm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/basic/orm.xml @@ -8,7 +8,7 @@ - org.hibernate.jpa.test.graphs.named.basic + org.hibernate.orm.test.entitygraph.named.basic diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/multiple/NamedEntityGraphsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/multiple/NamedEntityGraphsTest.java new file mode 100644 index 0000000000..aa1a30b7a4 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/multiple/NamedEntityGraphsTest.java @@ -0,0 +1,130 @@ +/* + * 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 . + */ +package org.hibernate.orm.test.entitygraph.named.multiple; + +import java.util.List; +import javax.persistence.AttributeNode; +import javax.persistence.Entity; +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; +import javax.persistence.Id; +import javax.persistence.NamedAttributeNode; +import javax.persistence.NamedEntityGraph; +import javax.persistence.NamedEntityGraphs; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.anyOf; +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.hibernate.testing.hamcrest.CollectionMatchers.hasSize; + +/** + * @author Steve Ebersole + */ +@DomainModel( + annotatedClasses = { + NamedEntityGraphsTest.Person.class, + NamedEntityGraphsTest.Employee.class + } +) +@SessionFactory +public class NamedEntityGraphsTest { + + @Test + void testIt(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph graph = em.getEntityGraph( "abc" ); + assertThat( graph, notNullValue() ); + graph = em.getEntityGraph( "xyz" ); + assertThat( graph, notNullValue() ); + } + ); + } + + @Test + void testAttributeNodesAreAvailable(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph graph = em.getEntityGraph( "name_salary_graph" ); + assertThat( graph, notNullValue() ); + + List> list = graph.getAttributeNodes(); + assertThat( list, notNullValue() ); + assertThat( list, hasSize( 2 ) ); + + AttributeNode attributeNode1 = list.get( 0 ); + AttributeNode attributeNode2 = list.get( 1 ); + assertThat( attributeNode1, notNullValue() ); + assertThat( attributeNode2, notNullValue() ); + + assertThat( attributeNode1.getAttributeName(), anyOf( is( "name" ), is( "salary" ) ) ); + assertThat( attributeNode2.getAttributeName(), anyOf( is( "name" ), is( "salary" ) ) ); + } + ); + } + + @Entity(name = "Person") + @NamedEntityGraphs({ + @NamedEntityGraph( name = "abc" ), + @NamedEntityGraph( name = "xyz" ) + }) + public static class Person { + @Id + public Long id; + } + + @Entity(name = "Employee") + @NamedEntityGraphs({ + @NamedEntityGraph( + name = "name_salary_graph", + includeAllAttributes = false, + attributeNodes = { + @NamedAttributeNode(value = "name"), + @NamedAttributeNode(value = "salary") + } + ), + }) + public static class Employee { + @Id + public Long id; + + private String name; + private double salary; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public double getSalary() { + return salary; + } + + public void setSalary(double salary) { + this.salary = salary; + } + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/Author.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/Author.java similarity index 93% rename from hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/Author.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/Author.java index ebb05ef0f2..735425f45d 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/Author.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/Author.java @@ -5,7 +5,7 @@ * See the lgpl.txt file in the root directory or . */ -package org.hibernate.jpa.test.graphs.named.subgraph; +package org.hibernate.orm.test.entitygraph.named.subgraph; import java.util.Date; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/Book.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/Book.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/Book.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/Book.java index 0d163f016f..0b4a8882dc 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/Book.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/Book.java @@ -5,7 +5,7 @@ * See the lgpl.txt file in the root directory or . */ -package org.hibernate.jpa.test.graphs.named.subgraph; +package org.hibernate.orm.test.entitygraph.named.subgraph; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/Prize.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/Prize.java similarity index 85% rename from hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/Prize.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/Prize.java index bdb1180bb9..786f72ba9b 100644 --- a/hibernate-core/src/test/java/org/hibernate/jpa/test/graphs/named/subgraph/Prize.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/Prize.java @@ -5,7 +5,7 @@ * See the lgpl.txt file in the root directory or . */ -package org.hibernate.jpa.test.graphs.named.subgraph; +package org.hibernate.orm.test.entitygraph.named.subgraph; /** * @author Vlad Mihalcea diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/SubgraphOrmNamedEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/SubgraphOrmNamedEntityGraphTest.java new file mode 100644 index 0000000000..adac675c86 --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/SubgraphOrmNamedEntityGraphTest.java @@ -0,0 +1,50 @@ +package org.hibernate.orm.test.entitygraph.named.subgraph; + +import java.util.List; +import javax.persistence.AttributeNode; +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; + +import org.hibernate.testing.TestForIssue; +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.notNullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hibernate.testing.hamcrest.CollectionMatchers.hasSize; + +@DomainModel( + xmlMappings = "org/hibernate/orm/test/entitygraph/named/subgraph/orm.xml" +) +@SessionFactory +public class SubgraphOrmNamedEntityGraphTest { + + @Test + @TestForIssue( jiraKey = "HHH-10633" ) + void testSubgraphsAreLoadedFromOrmXml(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager entityManager = session.unwrap( EntityManager.class ); + List> lneg = entityManager.getEntityGraphs( Book.class ); + + assertThat( lneg, notNullValue() ); + assertThat( lneg, hasSize( 2 ) ); + for ( EntityGraph neg : lneg ){ + if ( neg.getName().equalsIgnoreCase( "full" ) ) { + assertThat( neg.getAttributeNodes(), notNullValue() ); + for ( AttributeNode n : neg.getAttributeNodes() ) { + if ( n.getAttributeName().equalsIgnoreCase( "authors" ) ) { + assertThat(n.getSubgraphs().entrySet(), hasSize( 1 ) ); + List> attributeNodes = n.getSubgraphs().get(Author.class).getAttributeNodes(); + assertThat( attributeNodes, notNullValue() ); + assertThat(attributeNodes, hasSize( 3 ) ); + } + } + } + } + } + ); + } +} diff --git a/hibernate-core/src/test/resources/org/hibernate/jpa/test/graphs/named/subgraph/orm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/orm.xml similarity index 96% rename from hibernate-core/src/test/resources/org/hibernate/jpa/test/graphs/named/subgraph/orm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/orm.xml index c94b207b1a..3461944996 100644 --- a/hibernate-core/src/test/resources/org/hibernate/jpa/test/graphs/named/subgraph/orm.xml +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/named/subgraph/orm.xml @@ -7,7 +7,7 @@ - org.hibernate.jpa.test.graphs.named.subgraph + org.hibernate.orm.test.entitygraph.named.subgraph FIELD diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/AbstractEntityGraphTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/AbstractEntityGraphTest.java similarity index 98% rename from hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/AbstractEntityGraphTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/AbstractEntityGraphTest.java index 59e0d5739a..e90f16ee87 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/AbstractEntityGraphTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/AbstractEntityGraphTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.orm.test.loading.entitygraph.parser; +package org.hibernate.orm.test.entitygraph.parser; import java.util.Collection; import java.util.List; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/BasicEntityGraphTests.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/BasicEntityGraphTests.java new file mode 100644 index 0000000000..ef75511a6f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/BasicEntityGraphTests.java @@ -0,0 +1,124 @@ +/* + * 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 . + */ +package org.hibernate.orm.test.entitygraph.parser; + +import java.util.Set; +import javax.persistence.AttributeNode; +import javax.persistence.Entity; +import javax.persistence.EntityGraph; +import javax.persistence.EntityManager; +import javax.persistence.Id; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Subgraph; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Test; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.CoreMatchers.nullValue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hibernate.testing.hamcrest.CollectionMatchers.hasSize; +import static org.hibernate.testing.hamcrest.CollectionMatchers.isEmpty; +import static org.junit.jupiter.api.Assertions.fail; + +/** + * @author Steve Ebersole + * @author Nathan Xu + */ +@DomainModel( + annotatedClasses = { + BasicEntityGraphTests.Entity1.class + } +) +@SessionFactory +public class BasicEntityGraphTests { + + @Test + void testBasicGraphBuilding(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph graphRoot = em.createEntityGraph( Entity1.class ); + assertThat( graphRoot.getName(), nullValue() ); + assertThat( graphRoot.getAttributeNodes(), isEmpty() ); + } + ); + } + + @Test + void testBasicSubgraphBuilding(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph graphRoot = em.createEntityGraph( Entity1.class ); + Subgraph parentGraph = graphRoot.addSubgraph( "parent" ); + Subgraph childGraph = graphRoot.addSubgraph( "children" ); + + assertThat( graphRoot.getName(), nullValue() ); + assertThat( graphRoot.getAttributeNodes(), hasSize( 2 ) ); + graphRoot.getAttributeNodes().forEach( attributeNode -> + assertThat( attributeNode.getSubgraphs().containsValue( parentGraph ) + || attributeNode.getSubgraphs().containsValue( childGraph ), + is( true ) ) + ); + } + ); + } + + @Test + @SuppressWarnings("unchecked") + public void testBasicGraphImmutability(SessionFactoryScope scope) { + scope.inTransaction( + session -> { + EntityManager em = session.unwrap( EntityManager.class ); + EntityGraph graphRoot = em.createEntityGraph( Entity1.class ); + graphRoot.addSubgraph( "parent" ); + graphRoot.addSubgraph( "children" ); + + em.getEntityManagerFactory().addNamedEntityGraph( "immutable", graphRoot ); + + graphRoot = (EntityGraph) em.getEntityGraph( "immutable" ); + + assertThat( graphRoot.getName(), is( "immutable" ) ); + assertThat( graphRoot.getAttributeNodes(), hasSize( 2 ) ); + try { + graphRoot.addAttributeNodes( "parent" ); + fail( "Should have failed" ); + } + catch (IllegalStateException ignore) { + // expected outcome + } + + for ( AttributeNode attrNode : graphRoot.getAttributeNodes() ) { + assertThat( attrNode.getSubgraphs().entrySet(), hasSize( 1 ) ); + Subgraph subgraph = attrNode.getSubgraphs().values().iterator().next(); + try { + graphRoot.addAttributeNodes( "parent" ); + fail( "Should have failed" ); + } + catch (IllegalStateException ignore) { + // expected outcome + } + } + } + ); + } + + @Entity( name = "Entity1" ) + public static class Entity1 { + @Id + public Integer id; + public String name; + @ManyToOne + public Entity1 parent; + @OneToMany( mappedBy = "parent" ) + public Set children; + } +} diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/EntityGraphParserTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/EntityGraphParserTest.java similarity index 91% rename from hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/EntityGraphParserTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/EntityGraphParserTest.java index 7cbbeaa86e..edc2fc4ec9 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/EntityGraphParserTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/EntityGraphParserTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.orm.test.loading.entitygraph.parser; +package org.hibernate.orm.test.entitygraph.parser; import java.util.List; import java.util.Map; @@ -100,9 +100,7 @@ public class EntityGraphParserTest extends AbstractEntityGraphTest { } @Test -// @Ignore public void testMixParsingWithMaps() { - // Fails due to: https://hibernate.atlassian.net/browse/HHH-12696 String g = " name , linkToOne ( description, map . key ( name ) , map . value ( description ) , name ) , description , map . key ( name , description ) , map . value ( description ) "; g = g.replace( " ", " " ); for ( int i = 1; i <= 2; i++, g = g.replace( " ", "" ) ) { @@ -176,22 +174,7 @@ public class EntityGraphParserTest extends AbstractEntityGraphTest { } @Test -// @Ignore("Cannot run due to Hibernate bug: https://hibernate.atlassian.net/browse/HHH-10378") - // TODO Re-enable when Hibernate bug HHH-10378 is fixed public void testLinkSubtypeParsing() { - // https://hibernate.atlassian.net/browse/HHH-10378 - // - // Specifically the isTreatable(...) method in org.hibernate.jpa.graph.internal.AttributeNodeImpl - // - // It states: - // - // Check to make sure that the java type of the given entity persister is treatable as the given type. In other - // words, is the given type a subclass of the class represented by the persister. - // - // But that does not clearly match the implementation (seems opposite): - // - // return type.isAssignableFrom( entityPersister.getMappedClass() ); - RootGraphImplementor graph = parseGraph( "linkToOne(name, description), linkToOne(GraphParsingTestSubEntity: sub)" ); assertNotNull( graph ); @@ -228,7 +211,6 @@ public class EntityGraphParserTest extends AbstractEntityGraphTest { } @Test -// @Ignore("Cannot run due to Hibernate bug: https://hibernate.atlassian.net/browse/HHH-12696") public void testHHH12696MapSubgraphsKeyFirst() { EntityManager entityManager = getOrCreateEntityManager(); @@ -262,7 +244,6 @@ public class EntityGraphParserTest extends AbstractEntityGraphTest { } @Test -// @Ignore("Cannot run due to Hibernate bug: https://hibernate.atlassian.net/browse/HHH-12696") public void testHHH12696MapSubgraphsValueFirst() { EntityManager entityManager = getOrCreateEntityManager(); EntityGraph graph = entityManager.createEntityGraph( GraphParsingTestEntity.class ); diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/EntityGraphsTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/EntityGraphsTest.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/EntityGraphsTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/EntityGraphsTest.java index 26a0a75544..8733915ed8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/EntityGraphsTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/EntityGraphsTest.java @@ -4,7 +4,7 @@ * License: GNU Lesser General Public License (LGPL), version 2.1 or later. * See the lgpl.txt file in the root directory or . */ -package org.hibernate.orm.test.loading.entitygraph.parser; +package org.hibernate.orm.test.entitygraph.parser; import javax.persistence.EntityGraph; import javax.persistence.EntityManager; @@ -12,7 +12,6 @@ import javax.persistence.EntityManager; import org.hibernate.graph.EntityGraphs; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; public class EntityGraphsTest extends AbstractEntityGraphTest { @@ -63,10 +62,9 @@ public class EntityGraphsTest extends AbstractEntityGraphTest { } @Test - @Ignore("Cannot run due to Hibernate bug: https://hibernate.atlassian.net/browse/HHH-10378") public void testEqualLinksWithSubclassesEqual() { - EntityGraph a = parseGraph( "linkToOne(name), linkToOne:MockSubentity(description)" ); - EntityGraph b = parseGraph( "linkToOne:MockSubentity(description), linkToOne(name)" ); + EntityGraph a = parseGraph( "linkToOne(name), linkToOne(GraphParsingTestSubEntity: description)" ); + EntityGraph b = parseGraph( "linkToOne(GraphParsingTestSubEntity: description), linkToOne(name)" ); Assert.assertTrue( EntityGraphs.areEqual( a, b ) ); } @@ -85,9 +83,8 @@ public class EntityGraphsTest extends AbstractEntityGraphTest { } @Test - @Ignore("Cannot run due to Hibernate bug: https://hibernate.atlassian.net/browse/HHH-10378") public void testDifferentLinksEqual3() { - EntityGraph a = parseGraph( "linkToOne(name), linkToOne:MockSubentity(description)" ); + EntityGraph a = parseGraph( "linkToOne(name), linkToOne(GraphParsingTestSubEntity: description)" ); EntityGraph b = parseGraph( "linkToOne(name, description)" ); Assert.assertFalse( EntityGraphs.areEqual( a, b ) ); } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/GraphParsingTestEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/GraphParsingTestEntity.java similarity index 96% rename from hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/GraphParsingTestEntity.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/GraphParsingTestEntity.java index 0802573bc4..4bc7a26704 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/GraphParsingTestEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/GraphParsingTestEntity.java @@ -1,4 +1,4 @@ -package org.hibernate.orm.test.loading.entitygraph.parser; +package org.hibernate.orm.test.entitygraph.parser; import java.util.Map; import javax.persistence.Basic; diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/GraphParsingTestSubEntity.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/GraphParsingTestSubEntity.java similarity index 84% rename from hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/GraphParsingTestSubEntity.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/GraphParsingTestSubEntity.java index a9025ebb14..4a73f768f8 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/loading/entitygraph/parser/GraphParsingTestSubEntity.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/parser/GraphParsingTestSubEntity.java @@ -1,4 +1,4 @@ -package org.hibernate.orm.test.loading.entitygraph.parser; +package org.hibernate.orm.test.entitygraph.parser; import javax.persistence.Basic; import javax.persistence.Entity; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/Author.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/xml/Author.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/Author.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/xml/Author.java index 576db1df4c..ff8e135d59 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/Author.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/xml/Author.java @@ -5,7 +5,7 @@ * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.annotations.entityGraph; +package org.hibernate.orm.test.entitygraph.xml; import java.util.Date; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/Book.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/xml/Book.java similarity index 94% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/Book.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/xml/Book.java index 7191bcd314..7333f1dc9e 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/Book.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/xml/Book.java @@ -5,7 +5,7 @@ * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.annotations.entityGraph; +package org.hibernate.orm.test.entitygraph.xml; import java.util.Set; diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/OrmXmlParseTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/xml/OrmXmlParseTest.java similarity index 65% rename from hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/OrmXmlParseTest.java rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/xml/OrmXmlParseTest.java index 10146bb54e..e48539b9d5 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/OrmXmlParseTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/xml/OrmXmlParseTest.java @@ -5,15 +5,12 @@ * See the lgpl.txt file in the root directory or . */ -package org.hibernate.test.annotations.entityGraph; +package org.hibernate.orm.test.entitygraph.xml; import org.hibernate.cfg.Configuration; -import org.hibernate.internal.util.ConfigHelper; import org.hibernate.testing.TestForIssue; - -import org.junit.Test; - +import org.junit.jupiter.api.Test; /** * @author Etienne Miret @@ -22,9 +19,9 @@ public class OrmXmlParseTest { @Test @TestForIssue(jiraKey = "HHH-9247") - public void parseNamedAttributeNode() { + void parseNamedAttributeNode() { final Configuration cfg = new Configuration(); - cfg.addURL( ConfigHelper.findAsResource( "org/hibernate/test/annotations/entityGraph/orm.xml" ) ); + cfg.addURL( getClass().getResource( "orm.xml" ) ); cfg.buildMappings(); } diff --git a/hibernate-core/src/test/resources/org/hibernate/test/annotations/entityGraph/orm.xml b/hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/xml/orm.xml similarity index 100% rename from hibernate-core/src/test/resources/org/hibernate/test/annotations/entityGraph/orm.xml rename to hibernate-core/src/test/java/org/hibernate/orm/test/entitygraph/xml/orm.xml diff --git a/hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/package-info.java b/hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/package-info.java deleted file mode 100644 index 9759e682b2..0000000000 --- a/hibernate-core/src/test/java/org/hibernate/test/annotations/entityGraph/package-info.java +++ /dev/null @@ -1,12 +0,0 @@ -/* - * 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 . - */ - -/** - * This package groups tests about the JPA 2.1 Entity Graph feature. - * See section 3.7 from the JPA 2.1 specification. - */ -package org.hibernate.test.annotations.entityGraph; diff --git a/hibernate-testing/src/main/java/org/hibernate/testing/hamcrest/InitializationCheckMatcher.java b/hibernate-testing/src/main/java/org/hibernate/testing/hamcrest/InitializationCheckMatcher.java index 8ee9dd2f66..05b1791dbc 100644 --- a/hibernate-testing/src/main/java/org/hibernate/testing/hamcrest/InitializationCheckMatcher.java +++ b/hibernate-testing/src/main/java/org/hibernate/testing/hamcrest/InitializationCheckMatcher.java @@ -42,12 +42,12 @@ public class InitializationCheckMatcher extends BaseMatcher { @Override public boolean matches(Object item) { - final boolean initialized = Hibernate.isInitialized( item ); - return assertInitialized ? initialized : !initialized; + return assertInitialized == Hibernate.isInitialized( item ); } @Override public void describeTo(Description description) { - description.appendValue( "Hibernate#isInitialized == " + !assertInitialized ); + description.appendValue( "Hibernate#isInitialized() returns " + assertInitialized ); } + }