HHH-8760 improve EntityGraph JPQL query hint test
This commit is contained in:
parent
685e33ae0c
commit
e0d6cdc0f7
|
@ -119,14 +119,18 @@ public class QueryHints {
|
||||||
public static final String NATIVE_LOCKMODE = "org.hibernate.lockMode";
|
public static final String NATIVE_LOCKMODE = "org.hibernate.lockMode";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hint providing an EntityGraph. With JPQL/HQL, the sole functionality is attribute nodes are treated as
|
* Hint providing a "fetchgraph" EntityGraph. Attributes explicitly specified as AttributeNodes are treated as
|
||||||
* FetchType.EAGER. Laziness is not affected.
|
* FetchType.EAGER (via join fetch or subsequent select).
|
||||||
|
*
|
||||||
|
* Note: Currently, attributes that are not specified are treated as FetchType.LAZY or FetchType.EAGER depending
|
||||||
|
* on the attribute's definition in metadata, rather than forcing FetchType.LAZY.
|
||||||
*/
|
*/
|
||||||
public static final String FETCHGRAPH = "javax.persistence.fetchgraph";
|
public static final String FETCHGRAPH = "javax.persistence.fetchgraph";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hint providing an EntityGraph. With JPQL/HQL, the sole functionality is attribute nodes are treated as
|
* Hint providing a "loadgraph" EntityGraph. Attributes explicitly specified as AttributeNodes are treated as
|
||||||
* FetchType.EAGER. Laziness is not affected.
|
* FetchType.EAGER (via join fetch or subsequent select). Attributes that are not specified are treated as
|
||||||
|
* FetchType.LAZY or FetchType.EAGER depending on the attribute's definition in metadata
|
||||||
*/
|
*/
|
||||||
public static final String LOADGRAPH = "javax.persistence.loadgraph";
|
public static final String LOADGRAPH = "javax.persistence.loadgraph";
|
||||||
|
|
||||||
|
|
|
@ -101,14 +101,18 @@ public class QueryHints {
|
||||||
public static final String HINT_NATIVE_LOCKMODE = NATIVE_LOCKMODE;
|
public static final String HINT_NATIVE_LOCKMODE = NATIVE_LOCKMODE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hint providing an EntityGraph. With JPQL/HQL, the sole functionality is attribute nodes are treated as
|
* Hint providing a "fetchgraph" EntityGraph. Attributes explicitly specified as AttributeNodes are treated as
|
||||||
* FetchType.EAGER. Laziness is not affected.
|
* FetchType.EAGER (via join fetch or subsequent select).
|
||||||
|
*
|
||||||
|
* Note: Currently, attributes that are not specified are treated as FetchType.LAZY or FetchType.EAGER depending
|
||||||
|
* on the attribute's definition in metadata, rather than forcing FetchType.LAZY.
|
||||||
*/
|
*/
|
||||||
public static final String HINT_FETCHGRAPH = FETCHGRAPH;
|
public static final String HINT_FETCHGRAPH = FETCHGRAPH;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hint providing an EntityGraph. With JPQL/HQL, the sole functionality is attribute nodes are treated as
|
* Hint providing a "loadgraph" EntityGraph. Attributes explicitly specified as AttributeNodes are treated as
|
||||||
* FetchType.EAGER. Laziness is not affected.
|
* FetchType.EAGER (via join fetch or subsequent select). Attributes that are not specified are treated as
|
||||||
|
* FetchType.LAZY or FetchType.EAGER depending on the attribute's definition in metadata
|
||||||
*/
|
*/
|
||||||
public static final String HINT_LOADGRAPH = LOADGRAPH;
|
public static final String HINT_LOADGRAPH = LOADGRAPH;
|
||||||
|
|
||||||
|
|
|
@ -52,8 +52,12 @@ import org.junit.Test;
|
||||||
*/
|
*/
|
||||||
public class QueryHintEntityGraphTest extends BaseEntityManagerFunctionalTestCase {
|
public class QueryHintEntityGraphTest extends BaseEntityManagerFunctionalTestCase {
|
||||||
|
|
||||||
|
// TODO: Currently, "loadgraph" and "fetchgraph" operate identically in JPQL. The spec states that "fetchgraph"
|
||||||
|
// shall use LAZY for non-specified attributes, ignoring their metadata. Changes to ToOne select vs. join,
|
||||||
|
// allowing queries to force laziness, etc. will require changes here and impl logic.
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testQueryHintEntityGraph() {
|
public void testLoadGraph() {
|
||||||
EntityManager entityManager = getOrCreateEntityManager();
|
EntityManager entityManager = getOrCreateEntityManager();
|
||||||
entityManager.getTransaction().begin();
|
entityManager.getTransaction().begin();
|
||||||
|
|
||||||
|
@ -61,7 +65,7 @@ public class QueryHintEntityGraphTest extends BaseEntityManagerFunctionalTestCas
|
||||||
entityGraph.addAttributeNodes( "location" );
|
entityGraph.addAttributeNodes( "location" );
|
||||||
entityGraph.addAttributeNodes( "markets" );
|
entityGraph.addAttributeNodes( "markets" );
|
||||||
Query query = entityManager.createQuery( "from " + Company.class.getName() );
|
Query query = entityManager.createQuery( "from " + Company.class.getName() );
|
||||||
query.setHint( QueryHints.HINT_FETCHGRAPH, entityGraph );
|
query.setHint( QueryHints.HINT_LOADGRAPH, entityGraph );
|
||||||
Company company = (Company) query.getSingleResult();
|
Company company = (Company) query.getSingleResult();
|
||||||
|
|
||||||
entityManager.getTransaction().commit();
|
entityManager.getTransaction().commit();
|
||||||
|
@ -70,6 +74,9 @@ public class QueryHintEntityGraphTest extends BaseEntityManagerFunctionalTestCas
|
||||||
assertFalse( Hibernate.isInitialized( company.employees ) );
|
assertFalse( Hibernate.isInitialized( company.employees ) );
|
||||||
assertTrue( Hibernate.isInitialized( company.location ) );
|
assertTrue( Hibernate.isInitialized( company.location ) );
|
||||||
assertTrue( Hibernate.isInitialized( company.markets ) );
|
assertTrue( Hibernate.isInitialized( company.markets ) );
|
||||||
|
// With "loadgraph", non-specified attributes use the fetch modes defined in the mappings. So, here,
|
||||||
|
// @ElementCollection(fetch = FetchType.EAGER) should cause the follow-on selects to happen.
|
||||||
|
assertTrue( Hibernate.isInitialized( company.phoneNumbers ) );
|
||||||
|
|
||||||
entityManager = getOrCreateEntityManager();
|
entityManager = getOrCreateEntityManager();
|
||||||
entityManager.getTransaction().begin();
|
entityManager.getTransaction().begin();
|
||||||
|
@ -79,7 +86,7 @@ public class QueryHintEntityGraphTest extends BaseEntityManagerFunctionalTestCas
|
||||||
Subgraph<Employee> subgraph2 = subgraph1.addSubgraph( "managers" );
|
Subgraph<Employee> subgraph2 = subgraph1.addSubgraph( "managers" );
|
||||||
subgraph2.addAttributeNodes( "managers" );
|
subgraph2.addAttributeNodes( "managers" );
|
||||||
query = entityManager.createQuery( "from " + Company.class.getName() );
|
query = entityManager.createQuery( "from " + Company.class.getName() );
|
||||||
query.setHint( QueryHints.HINT_FETCHGRAPH, entityGraph );
|
query.setHint( QueryHints.HINT_LOADGRAPH, entityGraph );
|
||||||
company = (Company) query.getSingleResult();
|
company = (Company) query.getSingleResult();
|
||||||
|
|
||||||
entityManager.getTransaction().commit();
|
entityManager.getTransaction().commit();
|
||||||
|
@ -88,6 +95,9 @@ public class QueryHintEntityGraphTest extends BaseEntityManagerFunctionalTestCas
|
||||||
assertTrue( Hibernate.isInitialized( company.employees ) );
|
assertTrue( Hibernate.isInitialized( company.employees ) );
|
||||||
assertTrue( Hibernate.isInitialized( company.location ) );
|
assertTrue( Hibernate.isInitialized( company.location ) );
|
||||||
assertTrue( Hibernate.isInitialized( company.markets ) );
|
assertTrue( Hibernate.isInitialized( company.markets ) );
|
||||||
|
// With "loadgraph", non-specified attributes use the fetch modes defined in the mappings. So, here,
|
||||||
|
// @ElementCollection(fetch = FetchType.EAGER) should cause the follow-on selects to happen.
|
||||||
|
assertTrue( Hibernate.isInitialized( company.phoneNumbers ) );
|
||||||
|
|
||||||
boolean foundManager = false;
|
boolean foundManager = false;
|
||||||
Iterator<Employee> employeeItr = company.employees.iterator();
|
Iterator<Employee> employeeItr = company.employees.iterator();
|
||||||
|
@ -104,7 +114,7 @@ public class QueryHintEntityGraphTest extends BaseEntityManagerFunctionalTestCas
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testQueryHintEntityGraphWithExplicitFetch() {
|
public void testEntityGraphWithExplicitFetch() {
|
||||||
EntityManager entityManager = getOrCreateEntityManager();
|
EntityManager entityManager = getOrCreateEntityManager();
|
||||||
entityManager.getTransaction().begin();
|
entityManager.getTransaction().begin();
|
||||||
|
|
||||||
|
@ -112,9 +122,10 @@ public class QueryHintEntityGraphTest extends BaseEntityManagerFunctionalTestCas
|
||||||
entityGraph.addAttributeNodes( "location" );
|
entityGraph.addAttributeNodes( "location" );
|
||||||
entityGraph.addAttributeNodes( "markets" );
|
entityGraph.addAttributeNodes( "markets" );
|
||||||
entityGraph.addAttributeNodes( "employees" );
|
entityGraph.addAttributeNodes( "employees" );
|
||||||
|
// Ensure the EntityGraph and explicit fetches do not conflict.
|
||||||
Query query = entityManager.createQuery( "from " + Company.class.getName()
|
Query query = entityManager.createQuery( "from " + Company.class.getName()
|
||||||
+ " as c left join fetch c.location left join fetch c.employees" );
|
+ " as c left join fetch c.location left join fetch c.employees" );
|
||||||
query.setHint( QueryHints.HINT_FETCHGRAPH, entityGraph );
|
query.setHint( QueryHints.HINT_LOADGRAPH, entityGraph );
|
||||||
Company company = (Company) query.getSingleResult();
|
Company company = (Company) query.getSingleResult();
|
||||||
|
|
||||||
entityManager.getTransaction().commit();
|
entityManager.getTransaction().commit();
|
||||||
|
@ -123,6 +134,9 @@ public class QueryHintEntityGraphTest extends BaseEntityManagerFunctionalTestCas
|
||||||
assertTrue( Hibernate.isInitialized( company.employees ) );
|
assertTrue( Hibernate.isInitialized( company.employees ) );
|
||||||
assertTrue( Hibernate.isInitialized( company.location ) );
|
assertTrue( Hibernate.isInitialized( company.location ) );
|
||||||
assertTrue( Hibernate.isInitialized( company.markets ) );
|
assertTrue( Hibernate.isInitialized( company.markets ) );
|
||||||
|
// With "loadgraph", non-specified attributes use the fetch modes defined in the mappings. So, here,
|
||||||
|
// @ElementCollection(fetch = FetchType.EAGER) should cause the follow-on selects to happen.
|
||||||
|
assertTrue( Hibernate.isInitialized( company.phoneNumbers ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -157,6 +171,9 @@ public class QueryHintEntityGraphTest extends BaseEntityManagerFunctionalTestCas
|
||||||
company.markets = new HashSet<Market>();
|
company.markets = new HashSet<Market>();
|
||||||
company.markets.add( Market.SERVICES );
|
company.markets.add( Market.SERVICES );
|
||||||
company.markets.add( Market.TECHNOLOGY );
|
company.markets.add( Market.TECHNOLOGY );
|
||||||
|
company.phoneNumbers = new HashSet<String>();
|
||||||
|
company.phoneNumbers.add( "012-345-6789" );
|
||||||
|
company.phoneNumbers.add( "987-654-3210" );
|
||||||
entityManager.persist( company );
|
entityManager.persist( company );
|
||||||
|
|
||||||
entityManager.getTransaction().commit();
|
entityManager.getTransaction().commit();
|
||||||
|
@ -181,6 +198,9 @@ public class QueryHintEntityGraphTest extends BaseEntityManagerFunctionalTestCas
|
||||||
|
|
||||||
@ElementCollection
|
@ElementCollection
|
||||||
public Set<Market> markets;
|
public Set<Market> markets;
|
||||||
|
|
||||||
|
@ElementCollection(fetch = FetchType.EAGER)
|
||||||
|
public Set<String> phoneNumbers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
|
|
Loading…
Reference in New Issue