make use of JUnit5's ParameterizedTest to avoid some testing code duplication

This commit is contained in:
Nathan Xu 2020-03-13 12:38:29 -04:00 committed by Steve Ebersole
parent a9c2ea3a46
commit 12c272a9cd
3 changed files with 190 additions and 333 deletions

View File

@ -49,7 +49,10 @@ import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SessionFactoryScopeAware;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.platform.commons.util.CollectionUtils; import org.junit.platform.commons.util.CollectionUtils;
import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.instanceOf;
@ -76,15 +79,23 @@ import static org.junit.Assert.assertThat;
) )
@SessionFactory @SessionFactory
@TestForIssue( jiraKey = "HHH-13756" ) @TestForIssue( jiraKey = "HHH-13756" )
public class EntityGraphLoadPlanBuilderTest { public class EntityGraphLoadPlanBuilderTest implements SessionFactoryScopeAware {
@Test private SessionFactoryScope scope;
void testBasicFetchLoadPlanBuilding(SessionFactoryScope scope) {
@Override
public void injectSessionFactoryScope(SessionFactoryScope scope) {
this.scope = scope;
}
@ParameterizedTest
@EnumSource( GraphSemantic.class )
void testBasicLoadPlanBuilding(GraphSemantic graphSemantic) {
scope.inTransaction( scope.inTransaction(
em -> { em -> {
final RootGraphImplementor<Cat> eg = em.createEntityGraph( Cat.class ); final RootGraphImplementor<Cat> eg = em.createEntityGraph( Cat.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, GraphSemantic.FETCH, scope ); final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, graphSemantic, scope );
// Check the from-clause // Check the from-clause
assertEmptyJoinedGroup( sqlAst ); assertEmptyJoinedGroup( sqlAst );
@ -97,26 +108,41 @@ public class EntityGraphLoadPlanBuilderTest {
); );
} }
@Test @ParameterizedTest
void testFetchLoadPlanBuildingWithSubgraph(SessionFactoryScope scope) { @EnumSource( GraphSemantic.class )
void testLoadPlanBuildingWithSubgraph(GraphSemantic graphSemantic) {
scope.inTransaction( scope.inTransaction(
em -> { em -> {
final RootGraphImplementor<Cat> eg = em.createEntityGraph( Cat.class ); final RootGraphImplementor<Cat> eg = em.createEntityGraph( Cat.class );
eg.addSubgraph( "owner", Person.class ); eg.addSubgraph( "owner", Person.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, GraphSemantic.FETCH, scope ); final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, graphSemantic, scope );
// Check the from-clause // Check the from-clause
assertEntityValuedJoinedGroup( sqlAst, "owner", Person.class, this::assertPersonHomeAddressJoinedGroup ); assertEntityValuedJoinedGroup( sqlAst, "owner", Person.class, this::assertPersonHomeAddressJoinedGroup );
// Check the domain-result graph // Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class, entityFetch -> {} ); assertDomainResult( sqlAst, Cat.class, "owner", Person.class, entityFetch -> {
if ( graphSemantic == GraphSemantic.LOAD ) {
assertThat( entityFetch, instanceOf( EntityFetchJoinedImpl.class ) );
final EntityResult entityResult = ( (EntityFetchJoinedImpl) entityFetch ).getEntityResult();
final Map<String, Class<? extends Fetch>> fetchClassByAttributeName = entityResult.getFetches().stream().collect( Collectors.toMap(
fetch -> fetch.getFetchedMapping().getPartName(),
Fetch::getClass
) );
final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>();
expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class );
expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class );
expectedFetchClassByAttributeName.put( "company", EntityFetchDelayedImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
}
} );
} }
); );
} }
@Test @Test
void testFetchLoadPlanBuildingWithDeepSubgraph(SessionFactoryScope scope) { void testFetchLoadPlanBuildingWithDeepSubgraph() {
scope.inTransaction( scope.inTransaction(
em -> { em -> {
final RootGraphImplementor<Cat> eg = em.createEntityGraph( Cat.class ); final RootGraphImplementor<Cat> eg = em.createEntityGraph( Cat.class );
@ -168,62 +194,15 @@ public class EntityGraphLoadPlanBuilderTest {
); );
} }
@Test @ParameterizedTest
void testBasicLoadLoadPlanBuilding(SessionFactoryScope scope) { @EnumSource( GraphSemantic.class )
scope.inTransaction( void testBasicElementCollections(GraphSemantic graphSemantic) {
em -> {
final RootGraphImplementor<Cat> eg = em.createEntityGraph( Cat.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, GraphSemantic.LOAD, scope );
// Check the from-clause
assertEmptyJoinedGroup( sqlAst );
// Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class,
entityFetch -> assertThat( entityFetch, instanceOf( EntityFetchDelayedImpl.class ) ) );
}
);
}
@Test
void testLoadLoadPlanBuildingWithSubgraph(SessionFactoryScope scope) {
scope.inTransaction(
em -> {
final RootGraphImplementor<Cat> eg = em.createEntityGraph( Cat.class );
eg.addSubgraph( "owner", Person.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, GraphSemantic.LOAD, scope );
// Check the from-clause
assertEntityValuedJoinedGroup( sqlAst, "owner", Person.class, this::assertPersonHomeAddressJoinedGroup );
// Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class, entityFetch -> {
assertThat( entityFetch, instanceOf( EntityFetchJoinedImpl.class ) );
final EntityResult entityResult = ( (EntityFetchJoinedImpl) entityFetch ).getEntityResult();
final Map<String, Class<? extends Fetch>> fetchClassByAttributeName = entityResult.getFetches().stream().collect( Collectors.toMap(
fetch -> fetch.getFetchedMapping().getPartName(),
Fetch::getClass
) );
final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>();
expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class );
expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class );
expectedFetchClassByAttributeName.put( "company", EntityFetchDelayedImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
} );
}
);
}
@Test
void testBasicElementCollectionsLoadGraph(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
em -> { em -> {
final RootGraphImplementor<Dog> eg = em.createEntityGraph( Dog.class ); final RootGraphImplementor<Dog> eg = em.createEntityGraph( Dog.class );
eg.addAttributeNodes( "favorites" ); eg.addAttributeNodes( "favorites" );
final SelectStatement sqlAst = buildSqlSelectAst( Dog.class, eg, GraphSemantic.LOAD, scope ); final SelectStatement sqlAst = buildSqlSelectAst( Dog.class, eg, graphSemantic, scope );
// Check the from-clause // Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "favorites", tableGroup -> {} ); assertPluralAttributeJoinedGroup( sqlAst, "favorites", tableGroup -> {} );
@ -231,23 +210,9 @@ public class EntityGraphLoadPlanBuilderTest {
); );
} }
@Test @ParameterizedTest
void testBasicElementCollectionsFetchGraph(SessionFactoryScope scope) { @EnumSource( GraphSemantic.class )
scope.inTransaction( void testEmbeddedCollectionLoadGraph(GraphSemantic graphSemantic) {
em -> {
final RootGraphImplementor<Dog> eg = em.createEntityGraph( Dog.class );
eg.addAttributeNodes( "favorites" );
final SelectStatement sqlAst = buildSqlSelectAst( Dog.class, eg, GraphSemantic.FETCH, scope );
// Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "favorites", tableGroup -> {} );
}
);
}
@Test
void testEmbeddedCollectionLoadGraph(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
em -> { em -> {
final RootGraphImplementor<ExpressCompany> eg = em.createEntityGraph( ExpressCompany.class ); final RootGraphImplementor<ExpressCompany> eg = em.createEntityGraph( ExpressCompany.class );
@ -255,48 +220,33 @@ public class EntityGraphLoadPlanBuilderTest {
final SelectStatement sqlAst = buildSqlSelectAst( final SelectStatement sqlAst = buildSqlSelectAst(
ExpressCompany.class, ExpressCompany.class,
eg, GraphSemantic.LOAD, eg, graphSemantic,
scope scope
); );
// Check the from-clause // Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "shipAddresses", tableGroup -> { assertPluralAttributeJoinedGroup( sqlAst, "shipAddresses", tableGroup -> {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) ); if ( graphSemantic == GraphSemantic.LOAD ) {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) );
final TableGroup compositeTableGroup = CollectionUtils.getOnlyElement( tableGroup.getTableGroupJoins() ).getJoinedGroup(); final TableGroup compositeTableGroup = CollectionUtils.getOnlyElement( tableGroup.getTableGroupJoins() )
assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) ); .getJoinedGroup();
assertThat( compositeTableGroup.getTableGroupJoins(), hasSize( 1 ) ); assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) );
assertThat( compositeTableGroup.getTableGroupJoins(), hasSize( 1 ) );
final TableGroup countryTableGroup = CollectionUtils.getOnlyElement( compositeTableGroup.getTableGroupJoins() ).getJoinedGroup(); final TableGroup countryTableGroup = CollectionUtils.getOnlyElement( compositeTableGroup.getTableGroupJoins() )
assertThat( countryTableGroup.getModelPart().getPartName(), is( "country" ) ); .getJoinedGroup();
assertThat( countryTableGroup.getModelPart().getPartName(), is( "country" ) );
assertThat( countryTableGroup.getTableGroupJoins(), isEmpty() ); assertThat( countryTableGroup.getTableGroupJoins(), isEmpty() );
} ); }
else {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) );
} final TableGroup compositeTableGroup = CollectionUtils.getOnlyElement( tableGroup.getTableGroupJoins() ).getJoinedGroup();
); assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) );
} assertThat( compositeTableGroup.getTableGroupJoins(), isEmpty() );
}
@Test
void testEmbeddedCollectionFetchGraph(SessionFactoryScope scope) {
scope.inTransaction(
em -> {
final RootGraphImplementor<ExpressCompany> eg = em.createEntityGraph( ExpressCompany.class );
eg.addAttributeNodes( "shipAddresses" );
final SelectStatement sqlAst = buildSqlSelectAst(
ExpressCompany.class,
eg, GraphSemantic.FETCH,
scope
);
// Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "shipAddresses", tableGroup -> {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) );
final TableGroup compositeTableGroup = CollectionUtils.getOnlyElement( tableGroup.getTableGroupJoins() ).getJoinedGroup();
assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) );
assertThat( compositeTableGroup.getTableGroupJoins(), isEmpty() );
} ); } );
} }

View File

@ -55,7 +55,10 @@ import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SessionFactoryScopeAware;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.platform.commons.util.CollectionUtils; import org.junit.platform.commons.util.CollectionUtils;
import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.instanceOf;
@ -80,15 +83,23 @@ import static org.junit.Assert.assertThat;
) )
@SessionFactory @SessionFactory
@TestForIssue( jiraKey = "HHH-13756" ) @TestForIssue( jiraKey = "HHH-13756" )
public class CriteriaEntityGraphTest { public class CriteriaEntityGraphTest implements SessionFactoryScopeAware {
@Test private SessionFactoryScope scope;
void testBasicFetchSemantics(SessionFactoryScope scope) {
@Override
public void injectSessionFactoryScope(SessionFactoryScope scope) {
this.scope = scope;
}
@ParameterizedTest
@EnumSource( GraphSemantic.class )
void testBasicSemantics(GraphSemantic graphSemantic) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class ); final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, GraphSemantic.FETCH, session ); final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, graphSemantic, session );
// Check the from-clause // Check the from-clause
assertEmptyJoinedGroup( sqlAst ); assertEmptyJoinedGroup( sqlAst );
@ -101,26 +112,41 @@ public class CriteriaEntityGraphTest {
); );
} }
@Test @ParameterizedTest
void testFetchSemanticsWithSubgraph(SessionFactoryScope scope) { @EnumSource( GraphSemantic.class )
void testSemanticsWithSubgraph(GraphSemantic graphSemantic) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class ); final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class );
eg.addSubgraph( "owner", Person.class ); eg.addSubgraph( "owner", Person.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, GraphSemantic.FETCH, session ); final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, graphSemantic, session );
// Check the from-clause // Check the from-clause
assertEntityValuedJoinedGroup( sqlAst, "owner", Person.class, this::assertPersonHomeAddressJoinedGroup ); assertEntityValuedJoinedGroup( sqlAst, "owner", Person.class, this::assertPersonHomeAddressJoinedGroup );
// Check the domain-result graph // Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class, entityFetch -> {} ); assertDomainResult( sqlAst, Cat.class, "owner", Person.class, entityFetch -> {
if ( graphSemantic == GraphSemantic.LOAD ) {
assertThat( entityFetch, instanceOf( EntityFetchJoinedImpl.class ) );
final EntityResult entityResult = ( (EntityFetchJoinedImpl) entityFetch ).getEntityResult();
final Map<String, Class<? extends Fetch>> fetchClassByAttributeName = entityResult.getFetches().stream().collect( Collectors.toMap(
fetch -> fetch.getFetchedMapping().getPartName(),
Fetch::getClass
) );
final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>();
expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class );
expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class );
expectedFetchClassByAttributeName.put( "company", EntityFetchDelayedImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
}
} );
} }
); );
} }
@Test @Test
void testFetchSemanticsWithDeepSubgraph(SessionFactoryScope scope) { void testFetchSemanticsWithDeepSubgraph() {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class ); final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class );
@ -172,62 +198,15 @@ public class CriteriaEntityGraphTest {
); );
} }
@Test @ParameterizedTest
void testBasicLoadSemantics(SessionFactoryScope scope) { @EnumSource( GraphSemantic.class )
scope.inTransaction( void testBasicElementCollections(GraphSemantic graphSemantic) {
session -> {
final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, GraphSemantic.LOAD, session );
// Check the from-clause
assertEmptyJoinedGroup( sqlAst );
// Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class,
entityFetch -> assertThat( entityFetch, instanceOf( EntityFetchDelayedImpl.class ) ) );
}
);
}
@Test
void testLoadLoadPlanBuildingWithSubgraph(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class );
eg.addSubgraph( "owner", Person.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, eg, GraphSemantic.LOAD, session );
// Check the from-clause
assertEntityValuedJoinedGroup( sqlAst, "owner", Person.class, this::assertPersonHomeAddressJoinedGroup );
// Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class, entityFetch -> {
assertThat( entityFetch, instanceOf( EntityFetchJoinedImpl.class ) );
final EntityResult entityResult = ( (EntityFetchJoinedImpl) entityFetch ).getEntityResult();
final Map<String, Class<? extends Fetch>> fetchClassByAttributeName = entityResult.getFetches().stream().collect( Collectors.toMap(
fetch -> fetch.getFetchedMapping().getPartName(),
Fetch::getClass
) );
final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>();
expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class );
expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class );
expectedFetchClassByAttributeName.put( "company", EntityFetchDelayedImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
} );
}
);
}
@Test
void testBasicElementCollectionsLoadGraph(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final RootGraphImplementor<Dog> eg = session.createEntityGraph( Dog.class ); final RootGraphImplementor<Dog> eg = session.createEntityGraph( Dog.class );
eg.addAttributeNodes( "favorites" ); eg.addAttributeNodes( "favorites" );
final SelectStatement sqlAst = buildSqlSelectAst( Dog.class, eg, GraphSemantic.LOAD, session ); final SelectStatement sqlAst = buildSqlSelectAst( Dog.class, eg, graphSemantic, session );
// Check the from-clause // Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "favorites", tableGroup -> {} ); assertPluralAttributeJoinedGroup( sqlAst, "favorites", tableGroup -> {} );
@ -235,23 +214,9 @@ public class CriteriaEntityGraphTest {
); );
} }
@Test @ParameterizedTest
void testBasicElementCollectionsFetchGraph(SessionFactoryScope scope) { @EnumSource( GraphSemantic.class )
scope.inTransaction( void testEmbeddedCollection(GraphSemantic graphSemantic) {
session -> {
final RootGraphImplementor<Dog> eg = session.createEntityGraph( Dog.class );
eg.addAttributeNodes( "favorites" );
final SelectStatement sqlAst = buildSqlSelectAst( Dog.class, eg, GraphSemantic.FETCH, session );
// Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "favorites", tableGroup -> {} );
}
);
}
@Test
void testEmbeddedCollectionLoadGraph(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final RootGraphImplementor<ExpressCompany> eg = session.createEntityGraph( ExpressCompany.class ); final RootGraphImplementor<ExpressCompany> eg = session.createEntityGraph( ExpressCompany.class );
@ -259,48 +224,37 @@ public class CriteriaEntityGraphTest {
final SelectStatement sqlAst = buildSqlSelectAst( final SelectStatement sqlAst = buildSqlSelectAst(
ExpressCompany.class, ExpressCompany.class,
eg, GraphSemantic.LOAD, eg, graphSemantic,
session session
); );
// Check the from-clause // Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "shipAddresses", tableGroup -> { assertPluralAttributeJoinedGroup( sqlAst, "shipAddresses", tableGroup -> {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) ); if ( graphSemantic == GraphSemantic.LOAD ) {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) );
final TableGroup compositeTableGroup = tableGroup.getTableGroupJoins().iterator().next().getJoinedGroup(); final TableGroup compositeTableGroup = tableGroup.getTableGroupJoins()
assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) ); .iterator()
assertThat( compositeTableGroup.getTableGroupJoins(), hasSize( 1 ) ); .next()
.getJoinedGroup();
assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) );
assertThat( compositeTableGroup.getTableGroupJoins(), hasSize( 1 ) );
final TableGroup countryTableGroup = compositeTableGroup.getTableGroupJoins().iterator().next().getJoinedGroup(); final TableGroup countryTableGroup = compositeTableGroup.getTableGroupJoins()
assertThat( countryTableGroup.getModelPart().getPartName(), is( "country" ) ); .iterator()
.next()
.getJoinedGroup();
assertThat( countryTableGroup.getModelPart().getPartName(), is( "country" ) );
assertThat( countryTableGroup.getTableGroupJoins(), isEmpty() ); assertThat( countryTableGroup.getTableGroupJoins(), isEmpty() );
} ); }
else {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) );
} final TableGroup compositeTableGroup = CollectionUtils.getOnlyElement( tableGroup.getTableGroupJoins() ).getJoinedGroup();
); assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) );
} assertThat( compositeTableGroup.getTableGroupJoins(), isEmpty() );
}
@Test
void testEmbeddedCollectionFetchGraph(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final RootGraphImplementor<ExpressCompany> eg = session.createEntityGraph( ExpressCompany.class );
eg.addAttributeNodes( "shipAddresses" );
final SelectStatement sqlAst = buildSqlSelectAst(
ExpressCompany.class,
eg, GraphSemantic.FETCH,
session
);
// Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "shipAddresses", tableGroup -> {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) );
final TableGroup compositeTableGroup = CollectionUtils.getOnlyElement( tableGroup.getTableGroupJoins() ).getJoinedGroup();
assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) );
assertThat( compositeTableGroup.getTableGroupJoins(), isEmpty() );
} ); } );
} }
@ -411,6 +365,7 @@ public class CriteriaEntityGraphTest {
return sqmInterpretation.getSqlAst(); return sqmInterpretation.getSqlAst();
} }
@Entity(name = "Dog") @Entity(name = "Dog")
public static class Dog { public static class Dog {
@Id @Id

View File

@ -53,7 +53,10 @@ import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.SessionFactoryScopeAware;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.EnumSource;
import org.junit.platform.commons.util.CollectionUtils; import org.junit.platform.commons.util.CollectionUtils;
import static org.hamcrest.CoreMatchers.instanceOf; import static org.hamcrest.CoreMatchers.instanceOf;
@ -78,15 +81,23 @@ import static org.junit.Assert.assertThat;
) )
@SessionFactory @SessionFactory
@TestForIssue( jiraKey = "HHH-13756" ) @TestForIssue( jiraKey = "HHH-13756" )
public class HqlEntityGraphTest { public class HqlEntityGraphTest implements SessionFactoryScopeAware {
@Test private SessionFactoryScope scope;
void testBasicFetchSemantics(SessionFactoryScope scope) {
@Override
public void injectSessionFactoryScope(SessionFactoryScope scope) {
this.scope = scope;
}
@ParameterizedTest
@EnumSource( GraphSemantic.class )
void testBasicSemantics(GraphSemantic graphSemantic) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class ); final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, "select c from Cat c", eg, GraphSemantic.FETCH, session ); final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, "select c from Cat c", eg, graphSemantic, session );
// Check the from-clause // Check the from-clause
assertEmptyJoinedGroup( sqlAst ); assertEmptyJoinedGroup( sqlAst );
@ -99,26 +110,41 @@ public class HqlEntityGraphTest {
); );
} }
@Test @ParameterizedTest
void testFetchSemanticsWithSubgraph(SessionFactoryScope scope) { @EnumSource( GraphSemantic.class )
void testSemanticsWithSubgraph(GraphSemantic graphSemantic) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class ); final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class );
eg.addSubgraph( "owner", Person.class ); eg.addSubgraph( "owner", Person.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, "select c from Cat as c", eg, GraphSemantic.FETCH, session ); final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, "select c from Cat as c", eg, graphSemantic, session );
// Check the from-clause // Check the from-clause
assertEntityValuedJoinedGroup( sqlAst, "owner", Person.class, this::assertPersonHomeAddressJoinedGroup ); assertEntityValuedJoinedGroup( sqlAst, "owner", Person.class, this::assertPersonHomeAddressJoinedGroup );
// Check the domain-result graph // Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class, entityFetch -> {} ); assertDomainResult( sqlAst, Cat.class, "owner", Person.class, entityFetch -> {
if ( graphSemantic == GraphSemantic.LOAD ) {
assertThat( entityFetch, instanceOf( EntityFetchJoinedImpl.class ) );
final EntityResult entityResult = ( (EntityFetchJoinedImpl) entityFetch ).getEntityResult();
final Map<String, Class<? extends Fetch>> fetchClassByAttributeName = entityResult.getFetches().stream().collect( Collectors.toMap(
fetch -> fetch.getFetchedMapping().getPartName(),
Fetch::getClass
) );
final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>();
expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class );
expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class );
expectedFetchClassByAttributeName.put( "company", EntityFetchDelayedImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
}
} );
} }
); );
} }
@Test @Test
void testFetchSemanticsWithDeepSubgraph(SessionFactoryScope scope) { void testFetchSemanticsWithDeepSubgraph() {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class ); final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class );
@ -170,62 +196,15 @@ public class HqlEntityGraphTest {
); );
} }
@Test @ParameterizedTest
void testBasicLoadSemantics(SessionFactoryScope scope) { @EnumSource( GraphSemantic.class )
scope.inTransaction( void testBasicElementCollections(GraphSemantic graphSemantic) {
session -> {
final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, "select c from Cat as c", eg, GraphSemantic.LOAD, session );
// Check the from-clause
assertEmptyJoinedGroup( sqlAst );
// Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class,
entityFetch -> assertThat( entityFetch, instanceOf( EntityFetchDelayedImpl.class ) ) );
}
);
}
@Test
void testLoadLoadPlanBuildingWithSubgraph(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final RootGraphImplementor<Cat> eg = session.createEntityGraph( Cat.class );
eg.addSubgraph( "owner", Person.class );
final SelectStatement sqlAst = buildSqlSelectAst( Cat.class, "select c from Cat as c", eg, GraphSemantic.LOAD, session );
// Check the from-clause
assertEntityValuedJoinedGroup( sqlAst, "owner", Person.class, this::assertPersonHomeAddressJoinedGroup );
// Check the domain-result graph
assertDomainResult( sqlAst, Cat.class, "owner", Person.class, entityFetch -> {
assertThat( entityFetch, instanceOf( EntityFetchJoinedImpl.class ) );
final EntityResult entityResult = ( (EntityFetchJoinedImpl) entityFetch ).getEntityResult();
final Map<String, Class<? extends Fetch>> fetchClassByAttributeName = entityResult.getFetches().stream().collect( Collectors.toMap(
fetch -> fetch.getFetchedMapping().getPartName(),
Fetch::getClass
) );
final Map<String, Class<? extends Fetch>> expectedFetchClassByAttributeName = new HashMap<>();
expectedFetchClassByAttributeName.put( "pets", DelayedCollectionFetch.class );
expectedFetchClassByAttributeName.put( "homeAddress", EmbeddableFetchImpl.class );
expectedFetchClassByAttributeName.put( "company", EntityFetchDelayedImpl.class );
assertThat( fetchClassByAttributeName, is( expectedFetchClassByAttributeName ) );
} );
}
);
}
@Test
void testBasicElementCollectionsLoadGraph(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final RootGraphImplementor<Dog> eg = session.createEntityGraph( Dog.class ); final RootGraphImplementor<Dog> eg = session.createEntityGraph( Dog.class );
eg.addAttributeNodes( "favorites" ); eg.addAttributeNodes( "favorites" );
final SelectStatement sqlAst = buildSqlSelectAst( Dog.class, "select d from Dog as d", eg, GraphSemantic.LOAD, session ); final SelectStatement sqlAst = buildSqlSelectAst( Dog.class, "select d from Dog as d", eg, graphSemantic, session );
// Check the from-clause // Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "favorites", tableGroup -> {} ); assertPluralAttributeJoinedGroup( sqlAst, "favorites", tableGroup -> {} );
@ -233,23 +212,9 @@ public class HqlEntityGraphTest {
); );
} }
@Test @ParameterizedTest
void testBasicElementCollectionsFetchGraph(SessionFactoryScope scope) { @EnumSource( GraphSemantic.class )
scope.inTransaction( void testEmbeddedCollection(GraphSemantic graphSemantic) {
session -> {
final RootGraphImplementor<Dog> eg = session.createEntityGraph( Dog.class );
eg.addAttributeNodes( "favorites" );
final SelectStatement sqlAst = buildSqlSelectAst( Dog.class, "select d from Dog as d", eg, GraphSemantic.FETCH, session );
// Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "favorites", tableGroup -> {} );
}
);
}
@Test
void testEmbeddedCollectionLoadGraph(SessionFactoryScope scope) {
scope.inTransaction( scope.inTransaction(
session -> { session -> {
final RootGraphImplementor<ExpressCompany> eg = session.createEntityGraph( ExpressCompany.class ); final RootGraphImplementor<ExpressCompany> eg = session.createEntityGraph( ExpressCompany.class );
@ -258,51 +223,38 @@ public class HqlEntityGraphTest {
final SelectStatement sqlAst = buildSqlSelectAst( final SelectStatement sqlAst = buildSqlSelectAst(
ExpressCompany.class, ExpressCompany.class,
"select company from ExpressCompany as company", "select company from ExpressCompany as company",
eg, GraphSemantic.LOAD, eg, graphSemantic,
session session
); );
// Check the from-clause // Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "shipAddresses", tableGroup -> { assertPluralAttributeJoinedGroup( sqlAst, "shipAddresses", tableGroup -> {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) ); if ( graphSemantic == GraphSemantic.LOAD ) {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) );
final TableGroup compositeTableGroup = tableGroup.getTableGroupJoins().iterator().next().getJoinedGroup(); final TableGroup compositeTableGroup = tableGroup.getTableGroupJoins()
assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) ); .iterator()
assertThat( compositeTableGroup.getTableGroupJoins(), hasSize( 1 ) ); .next()
.getJoinedGroup();
assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) );
assertThat( compositeTableGroup.getTableGroupJoins(), hasSize( 1 ) );
final TableGroup countryTableGroup = compositeTableGroup.getTableGroupJoins().iterator().next().getJoinedGroup(); final TableGroup countryTableGroup = compositeTableGroup.getTableGroupJoins()
assertThat( countryTableGroup.getModelPart().getPartName(), is( "country" ) ); .iterator()
.next()
.getJoinedGroup();
assertThat( countryTableGroup.getModelPart().getPartName(), is( "country" ) );
assertThat( countryTableGroup.getTableGroupJoins(), isEmpty() ); assertThat( countryTableGroup.getTableGroupJoins(), isEmpty() );
}
else {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) );
final TableGroup compositeTableGroup = CollectionUtils.getOnlyElement( tableGroup.getTableGroupJoins() ).getJoinedGroup();
assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) );
assertThat( compositeTableGroup.getTableGroupJoins(), isEmpty() );
}
} ); } );
}
);
}
@Test
void testEmbeddedCollectionFetchGraph(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
final RootGraphImplementor<ExpressCompany> eg = session.createEntityGraph( ExpressCompany.class );
eg.addAttributeNodes( "shipAddresses" );
final SelectStatement sqlAst = buildSqlSelectAst(
ExpressCompany.class,
"select company from ExpressCompany as company",
eg, GraphSemantic.FETCH,
session
);
// Check the from-clause
assertPluralAttributeJoinedGroup( sqlAst, "shipAddresses", tableGroup -> {
assertThat( tableGroup.getTableGroupJoins(), hasSize( 1 ) );
final TableGroup compositeTableGroup = CollectionUtils.getOnlyElement( tableGroup.getTableGroupJoins() ).getJoinedGroup();
assertThat( compositeTableGroup, instanceOf( CompositeTableGroup.class ) );
assertThat( compositeTableGroup.getTableGroupJoins(), isEmpty() );
} );
} }
); );
} }