port entity graph legacy testing cases

This commit is contained in:
Nathan Xu 2020-06-28 14:24:12 -04:00 committed by Andrea Boriero
parent 9322273f39
commit 3d4cd3f7b3
57 changed files with 2177 additions and 1657 deletions

View File

@ -16,7 +16,7 @@ import javax.persistence.ManyToOne;
import javax.persistence.TypedQuery; import javax.persistence.TypedQuery;
import org.hibernate.dialect.H2Dialect; 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.GraphParser;
import org.hibernate.graph.EntityGraphs; import org.hibernate.graph.EntityGraphs;
import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.GraphSemantic;

View File

@ -1,2 +1,5 @@
## Ignore IntelliJ Antlr Plugin's output ## Ignore IntelliJ Antlr Plugin's output
gen/ gen/
## Ignore other generated code (e.g. Logger)
generated/

View File

@ -9,7 +9,7 @@ package org.hibernate.graph;
import java.util.List; import java.util.List;
import javax.persistence.metamodel.Attribute; 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. * Hibernate extension to the JPA entity-graph Subgraph contract.
@ -43,53 +43,40 @@ public interface SubGraph<J> extends Graph<J>, javax.persistence.Subgraph<J> {
} }
for ( Attribute<J, ?> node : attribute ) { for ( Attribute<J, ?> node : attribute ) {
// addAttributeNode( node ); assert node instanceof PersistentAttribute;
throw new NotYetImplementedFor6Exception( getClass() ); addAttributeNode( (PersistentAttribute<J, ?>) node );
} }
} }
@Override @Override
@SuppressWarnings("unchecked")
default <X> SubGraph<X> addSubgraph(Attribute<J, X> attribute) { default <X> SubGraph<X> addSubgraph(Attribute<J, X> attribute) {
throw new NotYetImplementedFor6Exception( getClass() ); return addSubGraph( (PersistentAttribute<J, X>) attribute );
// return addSubGraph( attribute );
} }
@Override @Override
@SuppressWarnings("unchecked")
default <X> SubGraph<? extends X> addSubgraph(Attribute<J, X> attribute, Class<? extends X> type) { default <X> SubGraph<? extends X> addSubgraph(Attribute<J, X> attribute, Class<? extends X> type) {
// return addSubGraph( attribute, type ); return addSubGraph( (PersistentAttribute<J, X>) attribute, type );
throw new NotYetImplementedFor6Exception( getClass() );
} }
@Override @Override
@SuppressWarnings("unchecked")
default <X> SubGraph<X> addSubgraph(String name) { default <X> SubGraph<X> addSubgraph(String name) {
return addSubGraph( name ); return addSubGraph( name );
} }
@Override @Override
@SuppressWarnings("unchecked")
default <X> SubGraph<X> addSubgraph(String name, Class<X> type) { default <X> SubGraph<X> addSubgraph(String name, Class<X> type) {
return addSubGraph( name, type ); return addSubGraph( name, type );
} }
@Override @Override
@SuppressWarnings("unchecked")
default <X> SubGraph<X> addKeySubgraph(Attribute<J, X> attribute) { default <X> SubGraph<X> addKeySubgraph(Attribute<J, X> attribute) {
throw new NotYetImplementedFor6Exception( getClass() ); return addKeySubGraph( (PersistentAttribute<J, X>) attribute );
// return addKeySubGraph( attribute );
} }
@Override @Override
@SuppressWarnings("unchecked")
default <X> SubGraph<? extends X> addKeySubgraph(Attribute<J, X> attribute, Class<? extends X> type) { default <X> SubGraph<? extends X> addKeySubgraph(Attribute<J, X> attribute, Class<? extends X> type) {
// return addKeySubGraph( attribute, type ); return addKeySubGraph( (PersistentAttribute<J, X>) attribute, type );
throw new NotYetImplementedFor6Exception( getClass() );
} }
@Override @Override
@ -98,13 +85,11 @@ public interface SubGraph<J> extends Graph<J>, javax.persistence.Subgraph<J> {
} }
@Override @Override
@SuppressWarnings("unchecked")
default <X> SubGraph<X> addKeySubgraph(String name, Class<X> type) { default <X> SubGraph<X> addKeySubgraph(String name, Class<X> type) {
return addKeySubGraph( name, type ); return addKeySubGraph( name, type );
} }
@Override @Override
@SuppressWarnings("unchecked")
default Class<J> getClassType() { default Class<J> getClassType() {
return getGraphedType().getJavaType(); return getGraphedType().getJavaType();
} }

View File

@ -8,7 +8,6 @@ package org.hibernate.loader.ast.internal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -20,14 +19,18 @@ import org.hibernate.LockOptions;
import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.profile.FetchProfile; import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.engine.spi.EffectiveEntityGraph;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SubselectFetch; 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.FilterHelper;
import org.hibernate.internal.util.MutableInteger; import org.hibernate.internal.util.MutableInteger;
import org.hibernate.loader.ast.spi.Loadable; import org.hibernate.loader.ast.spi.Loadable;
import org.hibernate.loader.ast.spi.Loader; import org.hibernate.loader.ast.spi.Loader;
import org.hibernate.metamodel.mapping.BasicValuedModelPart; import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
@ -187,14 +190,20 @@ public class LoaderSelectBuilder {
this.cachedDomainResult = cachedDomainResult; this.cachedDomainResult = cachedDomainResult;
this.numberOfKeysToLoad = numberOfKeysToLoad; this.numberOfKeysToLoad = numberOfKeysToLoad;
this.loadQueryInfluencers = loadQueryInfluencers; this.loadQueryInfluencers = loadQueryInfluencers;
if ( loadQueryInfluencers != null
&& loadQueryInfluencers.getEffectiveEntityGraph() != null EntityGraphTraversalState entityGraphTraversalState = null;
&& loadQueryInfluencers.getEffectiveEntityGraph().getSemantic() != null ) { if ( loadQueryInfluencers != null ) {
this.entityGraphTraversalState = new StandardEntityGraphTraversalStateImpl( loadQueryInfluencers.getEffectiveEntityGraph() ); final EffectiveEntityGraph effectiveEntityGraph = loadQueryInfluencers.getEffectiveEntityGraph();
} if ( effectiveEntityGraph != null ) {
else { final GraphSemantic graphSemantic = effectiveEntityGraph.getSemantic();
this.entityGraphTraversalState = null; 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.lockOptions = lockOptions != null ? lockOptions : LockOptions.NONE;
this.jdbcParameterConsumer = jdbcParameterConsumer; this.jdbcParameterConsumer = jdbcParameterConsumer;
} }
@ -473,25 +482,30 @@ public class LoaderSelectBuilder {
EntityGraphTraversalState.TraversalResult traversalResult = null; EntityGraphTraversalState.TraversalResult traversalResult = null;
// 'entity graph' takes precedence over 'fetch profile' if ( ! (fetchable instanceof CollectionPart ) ) {
if ( entityGraphTraversalState != null) { // 'entity graph' takes precedence over 'fetch profile'
traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable ); if ( entityGraphTraversalState != null ) {
fetchTiming = traversalResult.getFetchStrategy(); traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable );
joined = traversalResult.isJoined(); fetchTiming = traversalResult.getFetchStrategy();
} joined = traversalResult.isJoined();
else if ( loadQueryInfluencers.hasEnabledFetchProfiles() ) { }
if ( fetchParent instanceof EntityResultGraphNode ) { else if ( loadQueryInfluencers.hasEnabledFetchProfiles() ) {
final EntityResultGraphNode entityFetchParent = (EntityResultGraphNode) fetchParent; if ( fetchParent instanceof EntityResultGraphNode ) {
final EntityMappingType entityMappingType = entityFetchParent.getEntityValuedModelPart().getEntityMappingType(); final EntityResultGraphNode entityFetchParent = (EntityResultGraphNode) fetchParent;
final String fetchParentEntityName = entityMappingType.getEntityName(); final EntityMappingType entityMappingType = entityFetchParent.getEntityValuedModelPart()
final String fetchableRole = fetchParentEntityName + "." + fetchable.getFetchableName(); .getEntityMappingType();
final String fetchParentEntityName = entityMappingType.getEntityName();
final String fetchableRole = fetchParentEntityName + "." + fetchable.getFetchableName();
for ( String enabledFetchProfileName : loadQueryInfluencers.getEnabledFetchProfileNames() ) { for ( String enabledFetchProfileName : loadQueryInfluencers.getEnabledFetchProfileNames() ) {
final FetchProfile enabledFetchProfile = creationContext.getSessionFactory().getFetchProfile( enabledFetchProfileName ); final FetchProfile enabledFetchProfile = creationContext.getSessionFactory()
final org.hibernate.engine.profile.Fetch profileFetch = enabledFetchProfile.getFetchByRole( fetchableRole ); .getFetchProfile( enabledFetchProfileName );
final org.hibernate.engine.profile.Fetch profileFetch = enabledFetchProfile.getFetchByRole(
fetchableRole );
fetchTiming = FetchTiming.IMMEDIATE; fetchTiming = FetchTiming.IMMEDIATE;
joined = joined || profileFetch.getStyle() == org.hibernate.engine.profile.Fetch.Style.JOIN; 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 { try {
if ( !( fetchable instanceof BasicValuedModelPart ) && !( fetchable instanceof EmbeddedAttributeMapping ) ) { if ( changeFetchDepth ) {
fetchDepth++; fetchDepth++;
} }
final Fetch fetch = fetchable.generateFetch( final Fetch fetch = fetchable.generateFetch(
@ -541,10 +559,10 @@ public class LoaderSelectBuilder {
} }
} }
finally { finally {
if ( !( fetchable instanceof BasicValuedModelPart ) && !( fetchable instanceof EmbeddedAttributeMapping ) ) { if ( changeFetchDepth ) {
fetchDepth--; fetchDepth--;
} }
if ( entityGraphTraversalState != null ) { if ( entityGraphTraversalState != null && traversalResult != null ) {
entityGraphTraversalState.backtrack( traversalResult.getPreviousContext() ); entityGraphTraversalState.backtrack( traversalResult.getPreviousContext() );
} }
} }

View File

@ -20,10 +20,12 @@ import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.profile.FetchProfile; import org.hibernate.engine.profile.FetchProfile;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.graph.spi.AppliedGraph;
import org.hibernate.internal.FilterHelper; import org.hibernate.internal.FilterHelper;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.internal.util.collections.Stack; import org.hibernate.internal.util.collections.Stack;
import org.hibernate.internal.util.collections.StandardStack; import org.hibernate.internal.util.collections.StandardStack;
import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.ModelPartContainer; import org.hibernate.metamodel.mapping.ModelPartContainer;
@ -106,10 +108,10 @@ public class StandardSqmSelectTranslator
SqlAstCreationContext creationContext) { SqlAstCreationContext creationContext) {
super( creationContext, queryOptions, fetchInfluencers, domainParameterXref, domainParameterBindings ); super( creationContext, queryOptions, fetchInfluencers, domainParameterXref, domainParameterBindings );
if ( fetchInfluencers != null final AppliedGraph appliedGraph = queryOptions.getAppliedGraph();
&& fetchInfluencers.getEffectiveEntityGraph() != null if ( appliedGraph != null && appliedGraph.getSemantic() != null && appliedGraph.getGraph() != null ) {
&& fetchInfluencers.getEffectiveEntityGraph().getSemantic() != null ) { this.entityGraphTraversalState = new StandardEntityGraphTraversalStateImpl(
this.entityGraphTraversalState = new StandardEntityGraphTraversalStateImpl( fetchInfluencers.getEffectiveEntityGraph() ); appliedGraph.getSemantic(), appliedGraph.getGraph() );
} }
else { else {
this.entityGraphTraversalState = null; this.entityGraphTraversalState = null;
@ -331,24 +333,29 @@ public class StandardSqmSelectTranslator
// there was not an explicit fetch in the SQM // there was not an explicit fetch in the SQM
alias = null; alias = null;
if ( entityGraphTraversalState != null ) { if ( !( fetchable instanceof CollectionPart ) ) {
traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable ); if ( entityGraphTraversalState != null ) {
fetchTiming = traversalResult.getFetchStrategy(); traversalResult = entityGraphTraversalState.traverse( fetchParent, fetchable, isKeyFetchable );
joined = traversalResult.isJoined(); fetchTiming = traversalResult.getFetchStrategy();
} joined = traversalResult.isJoined();
else if ( getLoadQueryInfluencers().hasEnabledFetchProfiles() ) { }
if ( fetchParent instanceof EntityResultGraphNode ) { else if ( getLoadQueryInfluencers().hasEnabledFetchProfiles() ) {
final EntityResultGraphNode entityFetchParent = (EntityResultGraphNode) fetchParent; if ( fetchParent instanceof EntityResultGraphNode ) {
final EntityMappingType entityMappingType = entityFetchParent.getEntityValuedModelPart().getEntityMappingType(); final EntityResultGraphNode entityFetchParent = (EntityResultGraphNode) fetchParent;
final String fetchParentEntityName = entityMappingType.getEntityName(); final EntityMappingType entityMappingType = entityFetchParent.getEntityValuedModelPart()
final String fetchableRole = fetchParentEntityName + "." + fetchable.getFetchableName(); .getEntityMappingType();
final String fetchParentEntityName = entityMappingType.getEntityName();
final String fetchableRole = fetchParentEntityName + "." + fetchable.getFetchableName();
for ( String enabledFetchProfileName : getLoadQueryInfluencers().getEnabledFetchProfileNames() ) { for ( String enabledFetchProfileName : getLoadQueryInfluencers().getEnabledFetchProfileNames() ) {
final FetchProfile enabledFetchProfile = getCreationContext().getSessionFactory().getFetchProfile( enabledFetchProfileName ); final FetchProfile enabledFetchProfile = getCreationContext().getSessionFactory()
final org.hibernate.engine.profile.Fetch profileFetch = enabledFetchProfile.getFetchByRole( fetchableRole ); .getFetchProfile( enabledFetchProfileName );
final org.hibernate.engine.profile.Fetch profileFetch = enabledFetchProfile.getFetchByRole(
fetchableRole );
fetchTiming = FetchTiming.IMMEDIATE; fetchTiming = FetchTiming.IMMEDIATE;
joined = joined || profileFetch.getStyle() == org.hibernate.engine.profile.Fetch.Style.JOIN; joined = joined || profileFetch.getStyle() == org.hibernate.engine.profile.Fetch.Style.JOIN;
}
} }
} }
} }

View File

@ -7,14 +7,15 @@
package org.hibernate.sql.results.internal; package org.hibernate.sql.results.internal;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.PluralAttribute;
import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.EffectiveEntityGraph;
import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.spi.AttributeNodeImplementor; import org.hibernate.graph.spi.AttributeNodeImplementor;
import org.hibernate.graph.spi.GraphImplementor; import org.hibernate.graph.spi.GraphImplementor;
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.graph.spi.SubGraphImplementor; import org.hibernate.graph.spi.SubGraphImplementor;
import org.hibernate.metamodel.mapping.CollectionPart; import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
@ -34,13 +35,11 @@ public class StandardEntityGraphTraversalStateImpl implements EntityGraphTravers
private final GraphSemantic graphSemantic; private final GraphSemantic graphSemantic;
private GraphImplementor currentGraphContext; private GraphImplementor currentGraphContext;
public StandardEntityGraphTraversalStateImpl(EffectiveEntityGraph effectiveEntityGraph) { public StandardEntityGraphTraversalStateImpl(GraphSemantic graphSemantic, RootGraphImplementor rootGraphImplementor) {
assert effectiveEntityGraph != null; Objects.requireNonNull(graphSemantic, "graphSemantic cannot be null");
if ( effectiveEntityGraph.getSemantic() == null ) { Objects.requireNonNull( rootGraphImplementor, "rootGraphImplementor cannot be null" );
throw new IllegalArgumentException( "The graph has not defined semantic: " + effectiveEntityGraph ); this.graphSemantic = graphSemantic;
} this.currentGraphContext = rootGraphImplementor;
this.graphSemantic = effectiveEntityGraph.getSemantic();
this.currentGraphContext = effectiveEntityGraph.getGraph();
} }
@Override @Override
@ -50,6 +49,8 @@ public class StandardEntityGraphTraversalStateImpl implements EntityGraphTravers
@Override @Override
public TraversalResult traverse(FetchParent fetchParent, Fetchable fetchable, boolean exploreKeySubgraph) { public TraversalResult traverse(FetchParent fetchParent, Fetchable fetchable, boolean exploreKeySubgraph) {
assert !(fetchable instanceof CollectionPart);
final GraphImplementor previousContextRoot = currentGraphContext; final GraphImplementor previousContextRoot = currentGraphContext;
AttributeNodeImplementor attributeNode = null; AttributeNodeImplementor attributeNode = null;
if ( appliesTo( fetchParent ) ) { if ( appliesTo( fetchParent ) ) {

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<Entity1> graphRoot = em.createEntityGraph( Entity1.class );
assertNull( graphRoot.getName() );
assertEquals( 0, graphRoot.getAttributeNodes().size() );
}
@Test
public void testBasicSubgraphBuilding() {
EntityManager em = getOrCreateEntityManager();
EntityGraph<Entity1> graphRoot = em.createEntityGraph( Entity1.class );
Subgraph<Entity1> parentGraph = graphRoot.addSubgraph( "parent" );
Subgraph<Entity1> 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<Entity1> graphRoot = em.createEntityGraph( Entity1.class );
graphRoot.addSubgraph( "parent" );
graphRoot.addSubgraph( "children" );
em.getEntityManagerFactory().addNamedEntityGraph( "immutable", graphRoot );
graphRoot = (EntityGraph<Entity1>) 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<Entity1> children;
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<Foo> 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<Foo> 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<Foo> 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<Foo> foos = new HashSet<>();
}
@Entity(name = "Baz")
public static class Baz {
@Id
@GeneratedValue
public Integer id;
@OneToMany(mappedBy = "baz")
public Set<Foo> foos = new HashSet<>();
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<CustomerOrder> entityGraph = em.createEntityGraph( CustomerOrder.class );
//entityGraph.addAttributeNodes( "shippingAddress", "orderDate" );
entityGraph.addAttributeNodes( "shippingAddress" );
final Subgraph<OrderPosition> orderProductsSubgraph = entityGraph.addSubgraph( "orderPosition" );
//orderProductsSubgraph.addAttributeNodes( "amount" );
final Subgraph<Product> productSubgraph = orderProductsSubgraph.addSubgraph( "product" );
//productSubgraph.addAttributeNodes( "productName" );
TypedQuery<CustomerOrder> query = em.createQuery(
"SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class
);
query.setHint( "javax.persistence.loadgraph", entityGraph );
final List<CustomerOrder> 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<CustomerOrder> entityGraph = em.createEntityGraph( CustomerOrder.class );
entityGraph.addAttributeNodes( "shippingAddress", "orderDate" );
entityGraph.addAttributeNodes( "shippingAddress" );
final Subgraph<OrderPosition> orderProductsSubgraph = entityGraph.addSubgraph( "orderPosition" );
orderProductsSubgraph.addAttributeNodes( "amount" );
orderProductsSubgraph.addAttributeNodes( "product" );
final Subgraph<Product> productSubgraph = orderProductsSubgraph.addSubgraph( "product" );
productSubgraph.addAttributeNodes( "productName" );
TypedQuery<CustomerOrder> query = em.createQuery(
"SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class
);
query.setHint( "javax.persistence.loadgraph", entityGraph );
final List<CustomerOrder> 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<CustomerOrder> entityGraph = em.createEntityGraph( CustomerOrder.class );
EntityDomainType<CustomerOrder> customerOrderEntityType =
entityManagerFactory().getMetamodel().entity( CustomerOrder.class );
entityGraph.addAttributeNodes(
(Attribute) customerOrderEntityType.getAttribute( "shippingAddress" ),
(Attribute) customerOrderEntityType.getAttribute( "orderDate" )
);
entityGraph.addAttributeNodes( (Attribute) customerOrderEntityType.getAttribute( "shippingAddress" ) );
final Subgraph<OrderPosition> orderProductsSubgraph =
entityGraph.addSubgraph( (Attribute) customerOrderEntityType.getAttribute( "orderPosition" ) );
EntityDomainType<OrderPosition> positionEntityType =
entityManagerFactory().getMetamodel().entity( OrderPosition.class );
orderProductsSubgraph.addAttributeNodes( (Attribute) positionEntityType.getAttribute( "amount" ) );
orderProductsSubgraph.addAttributeNodes( (Attribute) positionEntityType.getAttribute( "product" ) );
final Subgraph<Product> productSubgraph =
orderProductsSubgraph.addSubgraph( (Attribute) positionEntityType.getAttribute( "product" ) );
EntityDomainType<Product> productEntityType = entityManagerFactory().getMetamodel().entity( Product.class );
productSubgraph.addAttributeNodes( (Attribute) productEntityType.getAttribute( "productName" ) );
TypedQuery<CustomerOrder> query = em.createQuery(
"SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class
);
query.setHint( "javax.persistence.loadgraph", entityGraph );
final List<CustomerOrder> 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<CustomerOrder> 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<CustomerOrder> 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<CustomerOrder> entityGraph) {
assertEquals(3, entityGraph.getAttributeNodes().size());
for ( AttributeNode<?> entityGraphAttributeNode : entityGraph.getAttributeNodes() ) {
if ( "orderPosition".equals( entityGraphAttributeNode.getAttributeName() ) ) {
Collection<Subgraph> orderPositionGraph = entityGraphAttributeNode.getSubgraphs().values();
assertEquals( 1, orderPositionGraph.size() );
List<AttributeNode<?>> 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;
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<Order> 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<Order> criteriaQuery = criteriaBuilder
.createQuery( Order.class );
criteriaQuery.from( Order.class );
EntityGraph<Order> 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<Product> products;
@OneToMany
@Fetch(FetchMode.SELECT)
private List<Tag> tags;
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public List<Product> getProducts() {
return this.products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public List<Tag> getTags() {
return this.tags;
}
public void setTags(List<Tag> 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;
}
}
}

View File

@ -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<EntityWithReference> 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;
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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;
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.test.graphs.inherited;
import javax.persistence.Entity;
/**
* @author Oliver Breidenbach
*/
@Entity
public class Foo extends MappedSupperclass {
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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;
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<Foo> entityGraph = em.createEntityGraph( Foo.class );
entityGraph.addSubgraph( "bar" );
Map<String, Object> properties = new HashMap<String, Object>();
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<Foo> entityGraph = em.createEntityGraph( Foo.class );
entityGraph.addSubgraph( "bars" );
Map<String, Object> properties = new HashMap<String, Object>();
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<Foo2> entityGraph = em.createEntityGraph( Foo2.class );
Subgraph<Foo> subgraphFoo = entityGraph.addSubgraph( "foo" );
subgraphFoo.addSubgraph( "bar" );
Map<String, Object> properties = new HashMap<String, Object>();
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<Foo2> entityGraph = em.createEntityGraph( Foo2.class );
Subgraph<Foo> subgraphFoo = entityGraph.addSubgraph( "foo" );
subgraphFoo.addSubgraph( "bars" );
Map<String, Object> properties = new HashMap<String, Object>();
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();
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<Bar> bars = new HashSet<Bar>();
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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 );
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.test.graphs.named.basic;
/**
* @author <a href="mailto:stliu@hibernate.org">Strong Liu</a>
*/
public class BasicAnnNamedEntityGraphTest extends AbstractNamedEntityGraphTest{
@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class[] { Person.class };
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
package org.hibernate.jpa.test.graphs.named.basic;
/**
* @author <a href="mailto:stliu@hibernate.org">Strong Liu</a>
*/
public class BasicOrmNamedEntityGraphTest extends AbstractNamedEntityGraphTest{
@Override
public String[] getEjb3DD() {
return new String[]{"org/hibernate/jpa/test/graphs/named/basic/orm.xml"};
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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;
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<AttributeNode<?>> 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()));
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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;
}

View File

@ -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<EntityGraph<? super Book>> lneg = entityManager.getEntityGraphs( Book.class );
assertNotNull( lneg );
Assert.assertEquals(2, lneg.size());
for (EntityGraph<? super Book> 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<javax.persistence.AttributeNode<?>> attributeNodes = n.getSubgraphs().get(Author.class).getAttributeNodes();
assertNotNull("Subgraph attributes missing", attributeNodes);
Assert.assertEquals("Subgraph wrong number of attributes ", 3, attributeNodes.size());
}
}
}
}
entityManager.close();
}
}

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * 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.time.Instant;
import java.util.ArrayList; import java.util.ArrayList;
@ -22,28 +22,39 @@ import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import javax.persistence.Table; import javax.persistence.Table;
import org.hibernate.Hibernate; import org.hibernate.graph.GraphParser;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.RootGraph;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.junit.After; import org.hibernate.testing.orm.junit.DomainModel;
import org.junit.Before; import org.hibernate.testing.orm.junit.SessionFactory;
import org.junit.Test; 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.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertFalse; import static org.hibernate.testing.hamcrest.InitializationCheckMatcher.isInitialized;
import static org.junit.Assert.assertTrue; import static org.hibernate.testing.hamcrest.InitializationCheckMatcher.isNotInitialized;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class EntityGraphFunctionalTests extends BaseEntityManagerFunctionalTestCase { @DomainModel(
annotatedClasses = {
EntityGraphFunctionalTests.User.class,
EntityGraphFunctionalTests.Issue.class,
EntityGraphFunctionalTests.Comment.class
}
)
@SessionFactory
public class EntityGraphFunctionalTests {
@Test @Test
@TestForIssue( jiraKey = "HHH-13175") @TestForIssue( jiraKey = "HHH-13175")
public void testSubsequentSelectFromFind() { void testSubsequentSelectFromFind(SessionFactoryScope scope) {
inTransaction( scope.inTransaction(
entityManagerFactory(),
session -> { session -> {
final RootGraph<Issue> graph = GraphParser.parse( Issue.class, "comments", session ); final RootGraph<Issue> graph = GraphParser.parse( Issue.class, "comments", session );
@ -53,30 +64,19 @@ public class EntityGraphFunctionalTests extends BaseEntityManagerFunctionalTestC
Collections.singletonMap( GraphSemantic.LOAD.getJpaHintName(), graph ) Collections.singletonMap( GraphSemantic.LOAD.getJpaHintName(), graph )
); );
assertTrue( Hibernate.isInitialized( issue ) ); assertThat( issue, isInitialized() );
assertTrue( Hibernate.isInitialized( issue.getComments() ) ); assertThat( issue.getComments(), isInitialized() );
assertTrue( Hibernate.isInitialized( issue.getReporter() ) ); assertThat( issue.getReporter(), isInitialized() );
assertTrue( Hibernate.isInitialized( issue.getAssignee() ) ); assertThat( issue.getAssignee(), isInitialized() );
assertFalse( Hibernate.isInitialized( issue.getAssignee().getAssignedIssues() ) ); assertThat( issue.getAssignee().getAssignedIssues(), isNotInitialized() );
} }
); );
} }
@Override @BeforeEach
protected Class<?>[] getAnnotatedClasses() { void prepareTestData(SessionFactoryScope scope) {
return new Class[] { User.class, Issue.class, Comment.class }; scope.inTransaction(
}
@Override
protected boolean createSchema() {
return true;
}
@Before
public void prepareTestData() {
inTransaction(
entityManagerFactory(),
session -> { session -> {
final User wesley = new User( "Wesley", "farmboy" ); final User wesley = new User( "Wesley", "farmboy" );
final User buttercup = new User( "Buttercup", "wishee" ); final User buttercup = new User( "Buttercup", "wishee" );
@ -104,10 +104,9 @@ public class EntityGraphFunctionalTests extends BaseEntityManagerFunctionalTestC
); );
} }
@After @AfterEach
public void cleanUpTestData() { void cleanUpTestData(SessionFactoryScope scope) {
inTransaction( scope.inTransaction(
entityManagerFactory(),
session -> { session -> {
session.createQuery( "delete from Comment" ).executeUpdate(); session.createQuery( "delete from Comment" ).executeUpdate();
session.createQuery( "delete from Issue" ).executeUpdate(); session.createQuery( "delete from Issue" ).executeUpdate();

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<Foo> 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<Foo> 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<Foo> 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<Foo> foos = new HashSet<>();
}
@Entity(name = "Baz")
public static class Baz {
@Id
@GeneratedValue
public Integer id;
@OneToMany(mappedBy = "baz")
public Set<Foo> foos = new HashSet<>();
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<CustomerOrder> entityGraph = em.createEntityGraph( CustomerOrder.class );
//entityGraph.addAttributeNodes( "shippingAddress", "orderDate" );
entityGraph.addAttributeNodes( "shippingAddress" );
final Subgraph<OrderPosition> orderProductsSubgraph = entityGraph.addSubgraph( "orderPosition" );
//orderProductsSubgraph.addAttributeNodes( "amount" );
final Subgraph<Product> productSubgraph = orderProductsSubgraph.addSubgraph( "product" );
//productSubgraph.addAttributeNodes( "productName" );
TypedQuery<CustomerOrder> query = em.createQuery(
"SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class
);
query.setHint( GraphSemantic.LOAD.getJpaHintName(), entityGraph );
final List<CustomerOrder> 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<CustomerOrder> entityGraph = em.createEntityGraph( CustomerOrder.class );
entityGraph.addAttributeNodes( "shippingAddress", "orderDate" );
entityGraph.addAttributeNodes( "shippingAddress" );
final Subgraph<OrderPosition> orderProductsSubgraph = entityGraph.addSubgraph( "orderPosition" );
orderProductsSubgraph.addAttributeNodes( "amount" );
orderProductsSubgraph.addAttributeNodes( "product" );
final Subgraph<Product> productSubgraph = orderProductsSubgraph.addSubgraph( "product" );
productSubgraph.addAttributeNodes( "productName" );
TypedQuery<CustomerOrder> query = em.createQuery(
"SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class
);
query.setHint( GraphSemantic.LOAD.getJpaHintName(), entityGraph );
final List<CustomerOrder> 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<CustomerOrder> entityGraph = em.createEntityGraph( CustomerOrder.class );
EntityDomainType<CustomerOrder> 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<OrderPosition> orderProductsSubgraph =
entityGraph.addSubgraph( (Attribute) customerOrderEntityType.getAttribute( "orderPosition" ) );
EntityDomainType<OrderPosition> positionEntityType =
scope.getSessionFactory().getMetamodel().entity( OrderPosition.class );
orderProductsSubgraph.addAttributeNodes( (Attribute) positionEntityType.getAttribute( "amount" ) );
orderProductsSubgraph.addAttributeNodes( (Attribute) positionEntityType.getAttribute( "product" ) );
final Subgraph<Product> productSubgraph =
orderProductsSubgraph.addSubgraph( (Attribute) positionEntityType.getAttribute( "product" ) );
EntityDomainType<Product> productEntityType = scope.getSessionFactory().getMetamodel().entity( Product.class );
productSubgraph.addAttributeNodes( (Attribute) productEntityType.getAttribute( "productName" ) );
TypedQuery<CustomerOrder> query = em.createQuery(
"SELECT o FROM EntityGraphUsingFetchGraphTest$CustomerOrder o", CustomerOrder.class
);
query.setHint( GraphSemantic.LOAD.getJpaHintName(), entityGraph );
final List<CustomerOrder> 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<CustomerOrder> 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<CustomerOrder> 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<CustomerOrder> entityGraph) {
assertThat(entityGraph.getAttributeNodes(), hasSize( 3 ) );
for ( AttributeNode<?> entityGraphAttributeNode : entityGraph.getAttributeNodes() ) {
if ( "orderPosition".equals( entityGraphAttributeNode.getAttributeName() ) ) {
Collection<Subgraph> orderPositionGraph = entityGraphAttributeNode.getSubgraphs().values();
assertThat( orderPositionGraph, hasSize( 1 ) );
List<AttributeNode<?>> 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;
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<Order> 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<Order> criteriaQuery = criteriaBuilder
.createQuery( Order.class );
criteriaQuery.from( Order.class );
EntityGraph<Order> 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<Product> products;
@OneToMany
@Fetch(FetchMode.SELECT)
private List<Tag> tags;
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public List<Product> getProducts() {
return this.products;
}
public void setProducts(List<Product> products) {
this.products = products;
}
public List<Tag> getTags() {
return this.tags;
}
public void setTags(List<Tag> 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;
}
}
}

View File

@ -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<EntityWithReference> 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;
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<Foo> entityGraph = em.createEntityGraph( Foo.class );
entityGraph.addSubgraph( "bar" );
Map<String, Object> 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<Foo> entityGraph = em.createEntityGraph( Foo.class );
entityGraph.addSubgraph( "bars" );
Map<String, Object> 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<Foo2> entityGraph = em.createEntityGraph( Foo2.class );
Subgraph<Foo> subgraphFoo = entityGraph.addSubgraph( "foo" );
subgraphFoo.addSubgraph( "bar" );
Map<String, Object> 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<Foo2> entityGraph = em.createEntityGraph( Foo2.class );
Subgraph<Foo> subgraphFoo = entityGraph.addSubgraph( "foo" );
subgraphFoo.addSubgraph( "bars" );
Map<String, Object> 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<Bar> bars = new HashSet<Bar>();
}
@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;
}
}

View File

@ -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<CEntity> 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<CEntity> entityGraph = entityManager.createEntityGraph( CEntity.class );
entityGraph.addAttributeNodes( "a", "b" );
entityGraph.addSubgraph( "dList" ).addAttributeNodes( "e" );
TypedQuery<CEntity> 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<CEntity> entityGraph = entityManager.createEntityGraph( CEntity.class );
entityGraph.addAttributeNodes( "a", "b" );
entityGraph.addSubgraph( "dList" ).addAttributeNodes( "e" );
TypedQuery<CEntity> 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<CEntity> entityGraph = entityManager.createEntityGraph( CEntity.class );
entityGraph.addSubgraph( "c" ).addAttributeNodes( "a" );
TypedQuery<CEntity> 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<CEntity> 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<CEntity> getCList() {
return cList;
}
public void setCList(List<CEntity> 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<CEntity> 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<CEntity> getCList() {
return cList;
}
public void setCList(List<CEntity> 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<DEntity> 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<DEntity> getDList() {
return dList;
}
public void setDList(List<DEntity> 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<DEntity> 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<DEntity> getDList() {
return dList;
}
public void setDList(List<DEntity> dList) {
this.dList = dList;
}
}
}

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * 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.HashMap;
import java.util.Map; import java.util.Map;
@ -341,8 +341,6 @@ public class CriteriaEntityGraphTest implements SessionFactoryScopeAware {
SessionImplementor session) { SessionImplementor session) {
final LoadQueryInfluencers loadQueryInfluencers = new LoadQueryInfluencers( session.getSessionFactory() ); final LoadQueryInfluencers loadQueryInfluencers = new LoadQueryInfluencers( session.getSessionFactory() );
final EffectiveEntityGraph effectiveEntityGraph = loadQueryInfluencers.getEffectiveEntityGraph();
effectiveEntityGraph.applyGraph( entityGraph, mode );
final CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder(); final CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery( entityType ); CriteriaQuery<T> criteriaQuery = criteriaBuilder.createQuery( entityType );
@ -350,6 +348,7 @@ public class CriteriaEntityGraphTest implements SessionFactoryScopeAware {
final QueryImplementor<T> query = session.createQuery( criteriaQuery ); final QueryImplementor<T> query = session.createQuery( criteriaQuery );
final HqlQueryImplementor<String> hqlQuery = (HqlQueryImplementor<String>) query; final HqlQueryImplementor<String> hqlQuery = (HqlQueryImplementor<String>) query;
hqlQuery.applyGraph( entityGraph, mode );
final SqmSelectStatement sqmStatement = (SqmSelectStatement) hqlQuery.getSqmStatement(); final SqmSelectStatement sqmStatement = (SqmSelectStatement) hqlQuery.getSqmStatement();

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * 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.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * 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.HashMap;
import java.util.Map; import java.util.Map;
@ -20,7 +20,6 @@ import javax.persistence.Id;
import javax.persistence.ManyToOne; import javax.persistence.ManyToOne;
import javax.persistence.OneToMany; import javax.persistence.OneToMany;
import org.hibernate.engine.spi.EffectiveEntityGraph;
import org.hibernate.engine.spi.LoadQueryInfluencers; import org.hibernate.engine.spi.LoadQueryInfluencers;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.graph.GraphSemantic; import org.hibernate.graph.GraphSemantic;
@ -340,14 +339,13 @@ public class HqlEntityGraphTest implements SessionFactoryScopeAware {
SessionImplementor session) { SessionImplementor session) {
final LoadQueryInfluencers loadQueryInfluencers = new LoadQueryInfluencers( session.getSessionFactory() ); final LoadQueryInfluencers loadQueryInfluencers = new LoadQueryInfluencers( session.getSessionFactory() );
final EffectiveEntityGraph effectiveEntityGraph = loadQueryInfluencers.getEffectiveEntityGraph();
effectiveEntityGraph.applyGraph( entityGraph, mode );
final QueryImplementor<T> query = session.createQuery( final QueryImplementor<T> query = session.createQuery(
hql, hql,
entityType entityType
); );
final HqlQueryImplementor<String> hqlQuery = (HqlQueryImplementor<String>) query; final HqlQueryImplementor<String> hqlQuery = (HqlQueryImplementor<String>) query;
hqlQuery.applyGraph( entityGraph, mode );
final SqmSelectStatement sqmStatement = (SqmSelectStatement) hqlQuery.getSqmStatement(); final SqmSelectStatement sqmStatement = (SqmSelectStatement) hqlQuery.getSqmStatement();

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later * 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 * 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 java.util.List;
import javax.persistence.CascadeType; import javax.persistence.CascadeType;

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.jpa.test.graphs.mappedbyid; package org.hibernate.orm.test.entitygraph.mappedbyid;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -23,7 +23,6 @@ import javax.persistence.criteria.Root;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
import org.hibernate.testing.FailureExpected;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.junit.Assert; import org.junit.Assert;
import org.junit.FixMethodOrder; import org.junit.FixMethodOrder;
@ -60,7 +59,6 @@ public class LoadGraphFindByIdTest extends BaseEntityManagerFunctionalTestCase {
@Test @Test
@TestForIssue(jiraKey = "HHH-10842") @TestForIssue(jiraKey = "HHH-10842")
@FailureExpected( jiraKey = "HHH-10842" )
public void findByPrimaryKeyWithId() { public void findByPrimaryKeyWithId() {
doInJPA( this::entityManagerFactory, em -> { doInJPA( this::entityManagerFactory, em -> {
User result = em.find( User.class, 1L, createProperties( em ) ); User result = em.find( User.class, 1L, createProperties( em ) );

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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 <a href="mailto:stliu@hibernate.org">Strong Liu</a>
*/
@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() );
}
);
}
}

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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 <a href="mailto:stliu@hibernate.org">Strong Liu</a>
*/
@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() );
}
);
}
}

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.jpa.test.graphs.named.basic; package org.hibernate.orm.test.entitygraph.named.basic;
import javax.persistence.Entity; import javax.persistence.Entity;
import javax.persistence.Id; import javax.persistence.Id;

View File

@ -8,7 +8,7 @@
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" <entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
version="2.1" version="2.1"
> >
<package>org.hibernate.jpa.test.graphs.named.basic</package> <package>org.hibernate.orm.test.entitygraph.named.basic</package>
<entity class="Person" metadata-complete="true" access="FIELD"> <entity class="Person" metadata-complete="true" access="FIELD">
<named-entity-graph/> <named-entity-graph/>
<attributes> <attributes>

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<AttributeNode<?>> 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;
}
}
}

View File

@ -5,7 +5,7 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.jpa.test.graphs.named.subgraph; package org.hibernate.orm.test.entitygraph.named.subgraph;
import java.util.Date; import java.util.Date;
import java.util.Set; import java.util.Set;

View File

@ -5,7 +5,7 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.jpa.test.graphs.named.subgraph; package org.hibernate.orm.test.entitygraph.named.subgraph;
import java.util.Set; import java.util.Set;

View File

@ -5,7 +5,7 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.jpa.test.graphs.named.subgraph; package org.hibernate.orm.test.entitygraph.named.subgraph;
/** /**
* @author Vlad Mihalcea * @author Vlad Mihalcea

View File

@ -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<EntityGraph<? super Book>> lneg = entityManager.getEntityGraphs( Book.class );
assertThat( lneg, notNullValue() );
assertThat( lneg, hasSize( 2 ) );
for ( EntityGraph<? super Book> 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<AttributeNode<?>> attributeNodes = n.getSubgraphs().get(Author.class).getAttributeNodes();
assertThat( attributeNodes, notNullValue() );
assertThat(attributeNodes, hasSize( 3 ) );
}
}
}
}
}
);
}
}

View File

@ -7,7 +7,7 @@
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" <entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm"
version="2.1" version="2.1"
> >
<package>org.hibernate.jpa.test.graphs.named.subgraph</package> <package>org.hibernate.orm.test.entitygraph.named.subgraph</package>
<access>FIELD</access> <access>FIELD</access>
<entity class="Book"> <entity class="Book">

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * 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.parser; package org.hibernate.orm.test.entitygraph.parser;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
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<Entity1> 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<Entity1> graphRoot = em.createEntityGraph( Entity1.class );
Subgraph<Entity1> parentGraph = graphRoot.addSubgraph( "parent" );
Subgraph<Entity1> 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<Entity1> graphRoot = em.createEntityGraph( Entity1.class );
graphRoot.addSubgraph( "parent" );
graphRoot.addSubgraph( "children" );
em.getEntityManagerFactory().addNamedEntityGraph( "immutable", graphRoot );
graphRoot = (EntityGraph<Entity1>) 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<Entity1> children;
}
}

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * 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.parser; package org.hibernate.orm.test.entitygraph.parser;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -100,9 +100,7 @@ public class EntityGraphParserTest extends AbstractEntityGraphTest {
} }
@Test @Test
// @Ignore
public void testMixParsingWithMaps() { 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 ) "; String g = " name , linkToOne ( description, map . key ( name ) , map . value ( description ) , name ) , description , map . key ( name , description ) , map . value ( description ) ";
g = g.replace( " ", " " ); g = g.replace( " ", " " );
for ( int i = 1; i <= 2; i++, g = g.replace( " ", "" ) ) { for ( int i = 1; i <= 2; i++, g = g.replace( " ", "" ) ) {
@ -176,22 +174,7 @@ public class EntityGraphParserTest extends AbstractEntityGraphTest {
} }
@Test @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() { 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<GraphParsingTestEntity> graph = parseGraph( "linkToOne(name, description), linkToOne(GraphParsingTestSubEntity: sub)" ); RootGraphImplementor<GraphParsingTestEntity> graph = parseGraph( "linkToOne(name, description), linkToOne(GraphParsingTestSubEntity: sub)" );
assertNotNull( graph ); assertNotNull( graph );
@ -228,7 +211,6 @@ public class EntityGraphParserTest extends AbstractEntityGraphTest {
} }
@Test @Test
// @Ignore("Cannot run due to Hibernate bug: https://hibernate.atlassian.net/browse/HHH-12696")
public void testHHH12696MapSubgraphsKeyFirst() { public void testHHH12696MapSubgraphsKeyFirst() {
EntityManager entityManager = getOrCreateEntityManager(); EntityManager entityManager = getOrCreateEntityManager();
@ -262,7 +244,6 @@ public class EntityGraphParserTest extends AbstractEntityGraphTest {
} }
@Test @Test
// @Ignore("Cannot run due to Hibernate bug: https://hibernate.atlassian.net/browse/HHH-12696")
public void testHHH12696MapSubgraphsValueFirst() { public void testHHH12696MapSubgraphsValueFirst() {
EntityManager entityManager = getOrCreateEntityManager(); EntityManager entityManager = getOrCreateEntityManager();
EntityGraph<GraphParsingTestEntity> graph = entityManager.createEntityGraph( GraphParsingTestEntity.class ); EntityGraph<GraphParsingTestEntity> graph = entityManager.createEntityGraph( GraphParsingTestEntity.class );

View File

@ -4,7 +4,7 @@
* License: GNU Lesser General Public License (LGPL), version 2.1 or later. * 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>. * 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.parser; package org.hibernate.orm.test.entitygraph.parser;
import javax.persistence.EntityGraph; import javax.persistence.EntityGraph;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
@ -12,7 +12,6 @@ import javax.persistence.EntityManager;
import org.hibernate.graph.EntityGraphs; import org.hibernate.graph.EntityGraphs;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
public class EntityGraphsTest extends AbstractEntityGraphTest { public class EntityGraphsTest extends AbstractEntityGraphTest {
@ -63,10 +62,9 @@ public class EntityGraphsTest extends AbstractEntityGraphTest {
} }
@Test @Test
@Ignore("Cannot run due to Hibernate bug: https://hibernate.atlassian.net/browse/HHH-10378")
public void testEqualLinksWithSubclassesEqual() { public void testEqualLinksWithSubclassesEqual() {
EntityGraph<GraphParsingTestEntity> a = parseGraph( "linkToOne(name), linkToOne:MockSubentity(description)" ); EntityGraph<GraphParsingTestEntity> a = parseGraph( "linkToOne(name), linkToOne(GraphParsingTestSubEntity: description)" );
EntityGraph<GraphParsingTestEntity> b = parseGraph( "linkToOne:MockSubentity(description), linkToOne(name)" ); EntityGraph<GraphParsingTestEntity> b = parseGraph( "linkToOne(GraphParsingTestSubEntity: description), linkToOne(name)" );
Assert.assertTrue( EntityGraphs.areEqual( a, b ) ); Assert.assertTrue( EntityGraphs.areEqual( a, b ) );
} }
@ -85,9 +83,8 @@ public class EntityGraphsTest extends AbstractEntityGraphTest {
} }
@Test @Test
@Ignore("Cannot run due to Hibernate bug: https://hibernate.atlassian.net/browse/HHH-10378")
public void testDifferentLinksEqual3() { public void testDifferentLinksEqual3() {
EntityGraph<GraphParsingTestEntity> a = parseGraph( "linkToOne(name), linkToOne:MockSubentity(description)" ); EntityGraph<GraphParsingTestEntity> a = parseGraph( "linkToOne(name), linkToOne(GraphParsingTestSubEntity: description)" );
EntityGraph<GraphParsingTestEntity> b = parseGraph( "linkToOne(name, description)" ); EntityGraph<GraphParsingTestEntity> b = parseGraph( "linkToOne(name, description)" );
Assert.assertFalse( EntityGraphs.areEqual( a, b ) ); Assert.assertFalse( EntityGraphs.areEqual( a, b ) );
} }

View File

@ -1,4 +1,4 @@
package org.hibernate.orm.test.loading.entitygraph.parser; package org.hibernate.orm.test.entitygraph.parser;
import java.util.Map; import java.util.Map;
import javax.persistence.Basic; import javax.persistence.Basic;

View File

@ -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.Basic;
import javax.persistence.Entity; import javax.persistence.Entity;

View File

@ -5,7 +5,7 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.annotations.entityGraph; package org.hibernate.orm.test.entitygraph.xml;
import java.util.Date; import java.util.Date;
import java.util.Set; import java.util.Set;

View File

@ -5,7 +5,7 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.annotations.entityGraph; package org.hibernate.orm.test.entitygraph.xml;
import java.util.Set; import java.util.Set;

View File

@ -5,15 +5,12 @@
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/ */
package org.hibernate.test.annotations.entityGraph; package org.hibernate.orm.test.entitygraph.xml;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
import org.hibernate.internal.util.ConfigHelper;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.junit.jupiter.api.Test;
import org.junit.Test;
/** /**
* @author Etienne Miret * @author Etienne Miret
@ -22,9 +19,9 @@ public class OrmXmlParseTest {
@Test @Test
@TestForIssue(jiraKey = "HHH-9247") @TestForIssue(jiraKey = "HHH-9247")
public void parseNamedAttributeNode() { void parseNamedAttributeNode() {
final Configuration cfg = new Configuration(); final Configuration cfg = new Configuration();
cfg.addURL( ConfigHelper.findAsResource( "org/hibernate/test/annotations/entityGraph/orm.xml" ) ); cfg.addURL( getClass().getResource( "orm.xml" ) );
cfg.buildMappings(); cfg.buildMappings();
} }

View File

@ -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 <http://www.gnu.org/licenses/lgpl-2.1.html>.
*/
/**
* 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;

View File

@ -42,12 +42,12 @@ public class InitializationCheckMatcher<T> extends BaseMatcher<T> {
@Override @Override
public boolean matches(Object item) { public boolean matches(Object item) {
final boolean initialized = Hibernate.isInitialized( item ); return assertInitialized == Hibernate.isInitialized( item );
return assertInitialized ? initialized : !initialized;
} }
@Override @Override
public void describeTo(Description description) { public void describeTo(Description description) {
description.appendValue( "Hibernate#isInitialized == " + !assertInitialized ); description.appendValue( "Hibernate#isInitialized() returns " + assertInitialized );
} }
} }