| /* |
| * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // Oracle - initial API and implementation from Oracle TopLink |
| |
| package org.eclipse.persistence.testing.tests.jpa.criteria; |
| |
| import java.util.List; |
| import java.util.Map; |
| |
| import jakarta.persistence.Query; |
| import jakarta.persistence.EntityManager; |
| import jakarta.persistence.Tuple; |
| import jakarta.persistence.TypedQuery; |
| import jakarta.persistence.criteria.CriteriaQuery; |
| import jakarta.persistence.criteria.Join; |
| import jakarta.persistence.criteria.CriteriaBuilder; |
| import jakarta.persistence.criteria.Root; |
| |
| import junit.framework.Test; |
| import junit.framework.TestSuite; |
| |
| import org.eclipse.persistence.config.CacheUsage; |
| import org.eclipse.persistence.config.QueryHints; |
| import org.eclipse.persistence.config.QueryType; |
| import org.eclipse.persistence.config.ResultSetConcurrency; |
| import org.eclipse.persistence.config.ResultSetType; |
| import org.eclipse.persistence.config.ResultType; |
| import org.eclipse.persistence.internal.sessions.AbstractSession; |
| import org.eclipse.persistence.jpa.JpaQuery; |
| import org.eclipse.persistence.queries.Cursor; |
| import org.eclipse.persistence.queries.ScrollableCursor; |
| import org.eclipse.persistence.sessions.DatabaseSession; |
| |
| import org.eclipse.persistence.testing.framework.junit.JUnitTestCase; |
| import org.eclipse.persistence.testing.framework.QuerySQLTracker; |
| import org.eclipse.persistence.testing.models.jpa.advanced.Employee; |
| import org.eclipse.persistence.testing.models.jpa.advanced.Address; |
| import org.eclipse.persistence.testing.models.jpa.advanced.EmployeePopulator; |
| import org.eclipse.persistence.testing.models.jpa.advanced.AdvancedTableCreator; |
| import org.eclipse.persistence.testing.tests.jpa.jpql.JUnitDomainObjectComparer; |
| |
| |
| /** |
| * <p> |
| * <b>Purpose</b>: Test advanced JPA Query functionality. |
| * <p> |
| * <b>Description</b>: This tests query hints, caching and query optimization. |
| * |
| */ |
| public class AdvancedQueryTestSuite extends JUnitTestCase { |
| |
| static JUnitDomainObjectComparer comparer; //the global comparer object used in all tests |
| |
| public AdvancedQueryTestSuite() { |
| super(); |
| } |
| |
| public AdvancedQueryTestSuite(String name) { |
| super(name); |
| } |
| |
| // This method is run at the start of EVERY test case method. |
| |
| @Override |
| public void setUp() { |
| |
| } |
| |
| // This method is run at the end of EVERY test case method. |
| |
| @Override |
| public void tearDown() { |
| clearCache(); |
| } |
| |
| //This suite contains all tests contained in this class |
| |
| public static Test suite() { |
| TestSuite suite = new TestSuite(); |
| suite.setName("AdvancedQueryTestSuite"); |
| suite.addTest(new AdvancedQueryTestSuite("testSetup")); |
| suite.addTest(new AdvancedQueryTestSuite("testQueryCacheFirstCacheHits")); |
| suite.addTest(new AdvancedQueryTestSuite("testQueryCacheOnlyCacheHits")); |
| suite.addTest(new AdvancedQueryTestSuite("testQueryCacheOnlyCacheHitsOnSession")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryPrimaryKeyCacheHits")); |
| suite.addTest(new AdvancedQueryTestSuite("testQueryExactPrimaryKeyCacheHits")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryTypeCacheHits")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryCache")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryREADLock")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryWRITELock")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryOPTIMISTICLock")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryOPTIMISTIC_FORCE_INCREMENTLock")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryPESSIMISTIC_READLock")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryPESSIMISTIC_WRITELock")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryPESSIMISTIC_FORCE_INCREMENTLock")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryPESSIMISTIC_READ_TIMEOUTLock")); |
| //suite.addTest(new AdvancedQueryTestSuite("testQueryPESSIMISTIC_WRITE_TIMEOUTLock")); |
| suite.addTest(new AdvancedQueryTestSuite("testObjectResultType")); |
| //suite.addTest(new AdvancedQueryTestSuite("testNativeResultType")); |
| suite.addTest(new AdvancedQueryTestSuite("testCursors")); |
| //suite.addTest(new AdvancedQueryTestSuite("testFetchGroups")); |
| //suite.addTest(new AdvancedQueryTestSuite("testMultipleNamedJoinFetchs")); |
| //suite.addTest(new AdvancedQueryTestSuite("testNativeQueryTransactions")); |
| |
| return suite; |
| } |
| |
| /** |
| * The setup is done as a test, both to record its failure, and to allow execution in the server. |
| */ |
| public void testSetup() { |
| clearCache(); |
| DatabaseSession session = JUnitTestCase.getServerSession(); |
| //create a new EmployeePopulator |
| EmployeePopulator employeePopulator = new EmployeePopulator(); |
| new AdvancedTableCreator().replaceTables(session); |
| //initialize the global comparer object |
| comparer = new JUnitDomainObjectComparer(); |
| //set the session for the comparer to use |
| comparer.setSession((AbstractSession)session.getActiveSession()); |
| //Populate the tables |
| employeePopulator.buildExamples(); |
| //Persist the examples in the database |
| employeePopulator.persistExample(session); |
| } |
| |
| /** |
| * Test that a cache hit will occur on a primary key query. |
| */ |
| public void testUntypedPath() { |
| EntityManager em = createEntityManager(); |
| beginTransaction(em); |
| QuerySQLTracker counter = null; |
| try { |
| // Load an employee into the cache. |
| CriteriaBuilder qb = em.getCriteriaBuilder(); |
| CriteriaQuery cq = qb.createQuery(Employee.class); |
| Query query = em.createQuery(cq); |
| List result = query.getResultList(); |
| Employee employee = (Employee)result.get(0); |
| |
| // Count SQL. |
| counter = new QuerySQLTracker(getServerSession()); |
| // Query by primary key. |
| CriteriaQuery<Employee> empCQ= qb.createQuery(Employee.class); |
| Root<Employee> from = empCQ.from(Employee.class); |
| Join<Employee, Address> join = from.join("address"); |
| empCQ.where(qb.greaterThanOrEqualTo(from.get("id").as(Integer.class), qb.literal(5))); |
| query = em.createQuery(empCQ); |
| query.setHint(QueryHints.CACHE_USAGE, CacheUsage.CheckCacheByExactPrimaryKey); |
| query.setParameter("id", employee.getId()); |
| Employee queryResult = (Employee)query.getSingleResult(); |
| if (queryResult != employee) { |
| fail("Employees are not equal: " + employee + ", " + queryResult); |
| } |
| if (counter.getSqlStatements().size() > 0) { |
| fail("Cache hit do not occur: " + counter.getSqlStatements()); |
| } |
| } finally { |
| rollbackTransaction(em); |
| if (counter != null) { |
| counter.remove(); |
| } |
| } |
| } |
| |
| |
| /** |
| * Test that a cache hit will occur on a primary key query. |
| */ |
| public void testTupleQuery() { |
| EntityManager em = createEntityManager(); |
| beginTransaction(em); |
| QuerySQLTracker counter = null; |
| try { |
| // Load an employee into the cache. |
| CriteriaBuilder qb = em.getCriteriaBuilder(); |
| |
| Query query = em.createQuery(em.getCriteriaBuilder().createQuery(Employee.class)); |
| List result = query.getResultList(); |
| Employee employee = (Employee)result.get(0); |
| |
| // Count SQL. |
| counter = new QuerySQLTracker(getServerSession()); |
| // Query by primary key. |
| CriteriaQuery<Tuple> cq = qb.createQuery(Tuple.class); |
| Root from = cq.from(Employee.class); |
| cq.multiselect(from.get("id"), from.get("firstName")); |
| cq.where(qb.and(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id")), qb.equal(from.get("firstName"), qb.parameter(from.get("firstName").getModel().getBindableJavaType(), "firstName")))); |
| TypedQuery<Tuple> typedQuery = em.createQuery(cq); |
| |
| typedQuery.setParameter("id", employee.getId()); |
| typedQuery.setParameter("firstName", employee.getFirstName()); |
| |
| Tuple queryResult = typedQuery.getSingleResult(); |
| assertTrue("Query Results do not match selection", queryResult.get(0).equals(employee.getId()) && queryResult.get(1).equals(employee.getFirstName())); |
| } finally { |
| rollbackTransaction(em); |
| if (counter != null) { |
| counter.remove(); |
| } |
| } |
| } |
| |
| /** |
| * Test cursored queries. |
| */ |
| public void testCursors() { |
| EntityManager em = createEntityManager(); |
| beginTransaction(em); |
| try { |
| // Test cusored stream. |
| Query query = em.createQuery(em.getCriteriaBuilder().createQuery(Employee.class)); |
| query.setHint(QueryHints.CURSOR, true); |
| query.setHint(QueryHints.CURSOR_INITIAL_SIZE, 2); |
| query.setHint(QueryHints.CURSOR_PAGE_SIZE, 5); |
| query.setHint(QueryHints.CURSOR_SIZE, "Select count(*) from CMP3_EMPLOYEE"); |
| Cursor cursor = (Cursor)query.getSingleResult(); |
| cursor.nextElement(); |
| cursor.size(); |
| cursor.close(); |
| |
| // Test cursor result API. |
| JpaQuery jpaQuery = (JpaQuery)((EntityManager)em.getDelegate()).createQuery(em.getCriteriaBuilder().createQuery(Employee.class)); |
| jpaQuery.setHint(QueryHints.CURSOR, true); |
| cursor = jpaQuery.getResultCursor(); |
| cursor.nextElement(); |
| cursor.size(); |
| cursor.close(); |
| |
| // Test scrollable cursor. |
| jpaQuery = (JpaQuery)((EntityManager)em.getDelegate()).createQuery(em.getCriteriaBuilder().createQuery(Employee.class)); |
| jpaQuery.setHint(QueryHints.SCROLLABLE_CURSOR, true); |
| jpaQuery.setHint(QueryHints.RESULT_SET_CONCURRENCY, ResultSetConcurrency.ReadOnly); |
| String resultSetType = ResultSetType.DEFAULT; |
| // HANA supports only TYPE_FORWARD_ONLY, see bug 384116 |
| if (getPlatform().isHANA()) { |
| resultSetType = ResultSetType.ForwardOnly; |
| } |
| jpaQuery.setHint(QueryHints.RESULT_SET_TYPE, resultSetType); |
| ScrollableCursor scrollableCursor = (ScrollableCursor)jpaQuery.getResultCursor(); |
| scrollableCursor.next(); |
| scrollableCursor.close(); |
| |
| } finally { |
| rollbackTransaction(em); |
| closeEntityManager(em); |
| } |
| } |
| |
| /** |
| * Test the result type of various queries. |
| */ |
| public void testObjectResultType() { |
| EntityManager em = createEntityManager(); |
| beginTransaction(em); |
| try { |
| // Load an employee into the cache. |
| Query query = em.createQuery(em.getCriteriaBuilder().createQuery(Employee.class)); |
| List result = query.getResultList(); |
| Employee employee = (Employee)result.get(0); |
| |
| CriteriaBuilder qb = em.getCriteriaBuilder(); |
| // Test multi object, as an array. |
| CriteriaQuery<?> cq = qb.createQuery(Object[].class); |
| Root<Employee> from = cq.from(Employee.class); |
| cq.multiselect(from, from.get("address"), from.get("id")); |
| cq.where(qb.and(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id")),qb.equal(from.get("firstName"), qb.parameter(from.get("firstName").getModel().getBindableJavaType(), "firstName")))); |
| query = em.createQuery(cq); |
| query.setParameter("id", employee.getId()); |
| query.setParameter("firstName", employee.getFirstName()); |
| Object[] arrayResult = (Object[])query.getSingleResult(); |
| if ((arrayResult.length != 3) && (arrayResult[0] != employee) || (arrayResult[1] != employee.getAddress()) || (!arrayResult[2].equals(employee.getId()))) { |
| fail("Array result not correct: " + arrayResult); |
| } |
| List listResult = query.getResultList(); |
| arrayResult = (Object[])listResult.get(0); |
| if ((arrayResult.length != 3) || (arrayResult[0] != employee) || (arrayResult[1] != employee.getAddress()) || (!arrayResult[2].equals(employee.getId()))) { |
| fail("Array result not correct: " + arrayResult); |
| } |
| |
| // Test single object, as an array. |
| cq = qb.createQuery(Object[].class); |
| from = cq.from(Employee.class); |
| cq.multiselect(from.get("id")); |
| cq.where(qb.and(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id")), (qb.equal(from.get("firstName"), qb.parameter(from.get("firstName").getModel().getBindableJavaType(), "firstName"))))); |
| query = em.createQuery(cq); |
| query.setHint(QueryHints.RESULT_TYPE, ResultType.Array); |
| query.setParameter("id", employee.getId()); |
| query.setParameter("firstName", employee.getFirstName()); |
| arrayResult = (Object[])query.getSingleResult(); |
| if ((arrayResult.length != 1) || (!arrayResult[0].equals(employee.getId()))) { |
| fail("Array result not correct: " + arrayResult); |
| } |
| listResult = query.getResultList(); |
| arrayResult = (Object[])listResult.get(0); |
| if ((arrayResult.length != 1) || (!arrayResult[0].equals(employee.getId()))) { |
| fail("Array result not correct: " + arrayResult); |
| } |
| |
| // Test multi object, as a Map. |
| cq = qb.createQuery(Object[].class); |
| from = cq.from(Employee.class); |
| cq.multiselect(from.alias("employee"), from.get("address").alias("address"), from.get("id").alias("id")); |
| cq.where(qb.and(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id")), qb.equal(from.get("firstName"), qb.parameter(from.get("firstName").getModel().getBindableJavaType(), "firstName")))); |
| query = em.createQuery(cq); |
| query.setHint(QueryHints.RESULT_TYPE, ResultType.Map); |
| query.setParameter("id", employee.getId()); |
| query.setParameter("firstName", employee.getFirstName()); |
| Map mapResult = (Map)query.getSingleResult(); |
| if ((mapResult.size() != 3) ||(mapResult.get("employee") != employee) || (mapResult.get("address") != employee.getAddress()) || (!mapResult.get("id").equals(employee.getId()))) { |
| fail("Map result not correct: " + mapResult); |
| } |
| listResult = query.getResultList(); |
| mapResult = (Map)listResult.get(0); |
| if ((mapResult.size() != 3) ||(mapResult.get("employee") != employee) || (mapResult.get("address") != employee.getAddress()) || (!mapResult.get("id").equals(employee.getId()))) { |
| fail("Map result not correct: " + mapResult); |
| } |
| |
| // Test single object, as a Map. |
| cq = qb.createQuery(Object[].class); |
| from = cq.from(Employee.class); |
| cq.multiselect(from.get("id").alias("id")); |
| cq.where(qb.and(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id")), qb.equal(from.get("firstName"), qb.parameter(from.get("firstName").getModel().getBindableJavaType(), "firstName")))); |
| query = em.createQuery(cq); |
| query.setHint(QueryHints.RESULT_TYPE, ResultType.Map); |
| query.setParameter("id", employee.getId()); |
| query.setParameter("firstName", employee.getFirstName()); |
| mapResult = (Map)query.getSingleResult(); |
| if ((mapResult.size() != 1) || (!mapResult.get("id").equals(employee.getId()))) { |
| fail("Map result not correct: " + mapResult); |
| } |
| listResult = query.getResultList(); |
| mapResult = (Map)listResult.get(0); |
| if ((mapResult.size() != 1) || (!mapResult.get("id").equals(employee.getId()))) { |
| fail("Map result not correct: " + mapResult); |
| } |
| |
| // Test single object, as an array. |
| cq = qb.createQuery(Employee.class); |
| from = cq.from(Employee.class); |
| cq.where(qb.and(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id")), qb.equal(from.get("firstName"), qb.parameter(from.get("firstName").getModel().getBindableJavaType(), "firstName")))); |
| query = em.createQuery(cq); |
| query.setHint(QueryHints.QUERY_TYPE, QueryType.Report); |
| query.setHint(QueryHints.RESULT_TYPE, ResultType.Array); |
| query.setParameter("id", employee.getId()); |
| query.setParameter("firstName", employee.getFirstName()); |
| arrayResult = (Object[])query.getSingleResult(); |
| if (arrayResult[0] != employee) { |
| fail("Array result not correct: " + arrayResult); |
| } |
| |
| // Test single object, as value. |
| cq = qb.createQuery(Object[].class); |
| from = cq.from(Employee.class); |
| cq.multiselect(from.get("id")); |
| cq.where(qb.and(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id")), qb.equal(from.get("firstName"), qb.parameter(from.get("firstName").getModel().getBindableJavaType(), "firstName")))); |
| query = em.createQuery(cq); |
| query.setParameter("id", employee.getId()); |
| query.setParameter("firstName", employee.getFirstName()); |
| Object valueResult = query.getSingleResult(); |
| if (! valueResult.equals(employee.getId())) { |
| fail("Value result not correct: " + valueResult); |
| } |
| listResult = query.getResultList(); |
| valueResult = listResult.get(0); |
| if (! valueResult.equals(employee.getId())) { |
| fail("Value result not correct: " + valueResult); |
| } |
| |
| // Test multi object, as value. |
| cq = qb.createQuery(Object[].class); |
| from = cq.from(Employee.class); |
| cq.multiselect(from.get("id"), from.get("firstName")); |
| cq.where(qb.and(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id")), qb.equal(from.get("firstName"), qb.parameter(from.get("firstName").getModel().getBindableJavaType(), "firstName")))); |
| query = em.createQuery(cq); |
| query.setHint(QueryHints.RESULT_TYPE, ResultType.Value); |
| query.setParameter("id", employee.getId()); |
| query.setParameter("firstName", employee.getFirstName()); |
| valueResult = query.getSingleResult(); |
| if (! valueResult.equals(employee.getId())) { |
| fail("Value result not correct: " + valueResult); |
| } |
| |
| // Test single object, as attribute. |
| cq = qb.createQuery(Object[].class); |
| from = cq.from(Employee.class); |
| cq.multiselect(from.get("id")); |
| cq.where(qb.and(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id")), qb.equal(from.get("firstName"), qb.parameter(from.get("firstName").getModel().getBindableJavaType(), "firstName")))); |
| query = em.createQuery(cq); |
| query.setHint(QueryHints.RESULT_TYPE, ResultType.Attribute); |
| query.setParameter("id", employee.getId()); |
| query.setParameter("firstName", employee.getFirstName()); |
| valueResult = query.getSingleResult(); |
| if (! valueResult.equals(employee.getId())) { |
| fail("Value result not correct: " + valueResult); |
| } |
| listResult = query.getResultList(); |
| valueResult = listResult.get(0); |
| if (! valueResult.equals(employee.getId())) { |
| fail("Value result not correct: " + valueResult); |
| } |
| } finally { |
| rollbackTransaction(em); |
| } |
| } |
| |
| /** |
| * Test that a cache hit will occur on a primary key query. |
| */ |
| public void testQueryExactPrimaryKeyCacheHits() { |
| EntityManager em = createEntityManager(); |
| beginTransaction(em); |
| QuerySQLTracker counter = null; |
| try { |
| // Load an employee into the cache. |
| CriteriaBuilder qb = em.getCriteriaBuilder(); |
| CriteriaQuery cq = qb.createQuery(Employee.class); |
| Query query = em.createQuery(cq); |
| List result = query.getResultList(); |
| Employee employee = (Employee)result.get(0); |
| |
| // Count SQL. |
| counter = new QuerySQLTracker(getServerSession()); |
| // Query by primary key. |
| cq = qb.createQuery(Employee.class); |
| Root from = cq.from(Employee.class); |
| cq.where(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id"))); |
| query = em.createQuery(cq); |
| query.setHint(QueryHints.CACHE_USAGE, CacheUsage.CheckCacheByExactPrimaryKey); |
| query.setParameter("id", employee.getId()); |
| Employee queryResult = (Employee)query.getSingleResult(); |
| if (queryResult != employee) { |
| fail("Employees are not equal: " + employee + ", " + queryResult); |
| } |
| if (counter.getSqlStatements().size() > 0) { |
| fail("Cache hit do not occur: " + counter.getSqlStatements()); |
| } |
| } finally { |
| rollbackTransaction(em); |
| if (counter != null) { |
| counter.remove(); |
| } |
| } |
| } |
| |
| /** |
| * Test that a cache hit will occur on a query. |
| */ |
| public void testQueryCacheFirstCacheHits() { |
| EntityManager em = createEntityManager(); |
| beginTransaction(em); |
| QuerySQLTracker counter = null; |
| try { |
| // Load an employee into the cache. |
| CriteriaBuilder qb = em.getCriteriaBuilder(); |
| CriteriaQuery cq = qb.createQuery(Employee.class); |
| Query query = em.createQuery(cq); |
| List result = query.getResultList(); |
| Employee employee = (Employee)result.get(result.size() - 1); |
| |
| // Count SQL. |
| counter = new QuerySQLTracker(getServerSession()); |
| // Query by primary key. |
| cq = qb.createQuery(Employee.class); |
| Root from = cq.from(Employee.class); |
| cq.where(qb.equal(from.get("firstName"), qb.parameter(from.get("firstName").getModel().getBindableJavaType(), "firstName"))); |
| query = em.createQuery(cq); |
| query.setHint(QueryHints.CACHE_USAGE, CacheUsage.CheckCacheThenDatabase); |
| query.setParameter("firstName", employee.getFirstName()); |
| Employee queryResult = (Employee)query.getSingleResult(); |
| if (!queryResult.getFirstName().equals(employee.getFirstName())) { |
| fail("Employees are not equal: " + employee + ", " + queryResult); |
| } |
| if (counter.getSqlStatements().size() > 0) { |
| fail("Cache hit do not occur: " + counter.getSqlStatements()); |
| } |
| } finally { |
| rollbackTransaction(em); |
| if (counter != null) { |
| counter.remove(); |
| } |
| } |
| } |
| |
| /** |
| * Test that a cache hit will occur on a query. |
| */ |
| public void testQueryCacheOnlyCacheHits() { |
| EntityManager em = createEntityManager(); |
| beginTransaction(em); |
| QuerySQLTracker counter = null; |
| try { |
| // Load an employee into the cache. |
| CriteriaBuilder qb = em.getCriteriaBuilder(); |
| CriteriaQuery cq = qb.createQuery(Employee.class); |
| Query query = em.createQuery(cq); |
| List result = query.getResultList(); |
| Employee employee = (Employee)result.get(result.size() - 1); |
| |
| // Count SQL. |
| counter = new QuerySQLTracker(getServerSession()); |
| // Query by primary key. |
| cq = qb.createQuery(Employee.class); |
| Root from = cq.from(Employee.class); |
| cq.where(qb.equal(from.get("firstName"), qb.parameter(from.get("firstName").getModel().getBindableJavaType(), "firstName"))); |
| query = em.createQuery(cq); |
| query.setHint(QueryHints.CACHE_USAGE, CacheUsage.CheckCacheOnly); |
| query.setParameter("firstName", employee.getFirstName()); |
| // Test that list works as well. |
| query.getResultList(); |
| if (counter.getSqlStatements().size() > 0) { |
| fail("Cache hit do not occur: " + counter.getSqlStatements()); |
| } |
| } finally { |
| rollbackTransaction(em); |
| if (counter != null) { |
| counter.remove(); |
| } |
| } |
| } |
| |
| /** |
| * Test that a cache hit will occur on a query when the object is not in the unit of work/em. |
| */ |
| public void testQueryCacheOnlyCacheHitsOnSession() { |
| EntityManager em = createEntityManager(); |
| beginTransaction(em); |
| QuerySQLTracker counter = null; |
| try { |
| // Load an employee into the cache. |
| CriteriaBuilder qb = em.getCriteriaBuilder(); |
| CriteriaQuery cq = qb.createQuery(Employee.class); |
| Query query = em.createQuery(cq); |
| List result = query.getResultList(); |
| Employee employee = (Employee)result.get(result.size() - 1); |
| |
| // Count SQL. |
| counter = new QuerySQLTracker(getServerSession()); |
| // Query by primary key. |
| rollbackTransaction(em); |
| closeEntityManager(em); |
| em = createEntityManager(); |
| beginTransaction(em); |
| cq = qb.createQuery(Employee.class); |
| Root from = cq.from(Employee.class); |
| cq.where(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id"))); |
| query = em.createQuery(cq); |
| query.setHint(QueryHints.QUERY_TYPE, QueryType.ReadObject); |
| query.setHint(QueryHints.CACHE_USAGE, CacheUsage.CheckCacheOnly); |
| query.setParameter("id", employee.getId()); |
| if (query.getSingleResult() == null) { |
| fail("Query did not check session cache."); |
| } |
| if (counter.getSqlStatements().size() > 0) { |
| fail("Cache hit do not occur: " + counter.getSqlStatements()); |
| } |
| rollbackTransaction(em); |
| closeEntityManager(em); |
| em = createEntityManager(); |
| beginTransaction(em); |
| cq = qb.createQuery(Employee.class); |
| from = cq.from(Employee.class); |
| cq.where(qb.equal(from.get("id"), qb.parameter(from.get("id").getModel().getBindableJavaType(), "id"))); |
| query = em.createQuery(cq); |
| query.setHint(QueryHints.CACHE_USAGE, CacheUsage.CheckCacheOnly); |
| query.setParameter("id", employee.getId()); |
| if (query.getResultList().size() != 1) { |
| fail("Query did not check session cache."); |
| } |
| if (counter.getSqlStatements().size() > 0) { |
| fail("Cache hit do not occur: " + counter.getSqlStatements()); |
| } |
| } finally { |
| if (counter != null) { |
| counter.remove(); |
| } |
| rollbackTransaction(em); |
| closeEntityManager(em); |
| } |
| } |
| } |