blob: 5e15e6cd20cd622d135843fc37abb3f603ac0865 [file] [log] [blame]
/*
* Copyright (c) 2005, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2015 SAP. 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:
// SAP - initial API and implementation
package org.eclipse.persistence.testing.tests.wdf.jpa1.query;
import static jakarta.persistence.FlushModeType.AUTO;
import static jakarta.persistence.FlushModeType.COMMIT;
import static org.junit.Assert.assertEquals;
import java.sql.SQLException;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import jakarta.persistence.EntityManager;
import jakarta.persistence.FlushModeType;
import jakarta.persistence.NoResultException;
import jakarta.persistence.NonUniqueResultException;
import jakarta.persistence.PersistenceException;
import jakarta.persistence.Query;
import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment;
import org.eclipse.persistence.testing.framework.wdf.ToBeInvestigated;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department;
import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Project;
import org.eclipse.persistence.testing.models.wdf.jpa1.types.BasicTypesFieldAccess;
import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base;
import org.junit.Test;
@SuppressWarnings("unchecked")
public class TestSimpleQuery extends JPA1Base {
private final Set<Department> ALL_DEPARTMENTS = new HashSet<Department>();
private final Department dep10 = new Department(10, "ten");
private final Department dep20 = new Department(20, "twenty");
private void init() throws SQLException {
clearAllTables();
ALL_DEPARTMENTS.add(dep10);
ALL_DEPARTMENTS.add(dep20);
JPAEnvironment env = getEnvironment();
EntityManager em = env.getEntityManager();
try {
env.beginTransaction(em);
em.persist(dep10);
em.persist(dep20);
env.commitTransactionAndClear(em);
} finally {
closeEntityManager(em);
}
}
@Test
public void testSelectAllDepartments() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
boolean extended = getEnvironment().usesExtendedPC();
try {
Query query = em.createQuery("select d from Department d");
List result = query.getResultList();
verify(result.size() == 2, "wrong resultcount");
Iterator iter = result.iterator();
Set<Department> actualSet = new HashSet<Department>();
while (iter.hasNext()) {
Department entity = (Department) iter.next();
if (extended) {
verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
} else {
verify(!em.contains(entity), "entity manager contains result read outside transaction");
}
actualSet.add(entity);
}
verify(ALL_DEPARTMENTS.equals(actualSet), "the sets are somehow different");
} finally {
closeEntityManager(em);
}
}
@Test
public void testSelectDepartmentByName() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
boolean extended = getEnvironment().usesExtendedPC();
try {
Query query = em.createQuery("select d from Department d where d.name = ?1");
query.setParameter(1, "twenty");
List result = query.getResultList();
Iterator iter = result.iterator();
verify(iter.hasNext(), "row not found");
Department entity = (Department) iter.next();
if (extended) {
verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
} else {
verify(!em.contains(entity), "entity manager contains result read outside transaction");
}
verify(entity.equals(dep20), " got wrong department");
verify(!iter.hasNext(), "too many rows");
query = em.createQuery("select distinct d from Department d where d.name = ?1");
query.setParameter(1, "twenty");
result = query.getResultList();
iter = result.iterator();
verify(iter.hasNext(), "row not found");
entity = (Department) iter.next();
if (extended) {
verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
} else {
verify(!em.contains(entity), "entity manager contains result read outside transaction");
}
verify(entity.equals(dep20), " got wrong department");
verify(!iter.hasNext(), "too many rows");
query = em.createQuery("select d from Department d where d.name like 'twenty'");
result = query.getResultList();
iter = result.iterator();
verify(iter.hasNext(), "row not found");
entity = (Department) iter.next();
if (extended) {
verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
} else {
verify(!em.contains(entity), "entity manager contains result read outside transaction");
}
verify(entity.equals(dep20), " got wrong department");
verify(!iter.hasNext(), "too many rows");
query = em.createQuery("select d from Department d where d.name like 'twen%'");
result = query.getResultList();
iter = result.iterator();
verify(iter.hasNext(), "row not found");
entity = (Department) iter.next();
if (extended) {
verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
} else {
verify(!em.contains(entity), "entity manager contains result read outside transaction");
}
verify(entity.equals(dep20), " got wrong department");
verify(!iter.hasNext(), "too many rows");
} finally {
closeEntityManager(em);
}
}
@Test
public void testSelectInTransaction() throws SQLException {
init();
JPAEnvironment env = getEnvironment();
EntityManager em = env.getEntityManager();
try {
env.beginTransaction(em);
Query query = em.createQuery("select d from Department d");
List result = query.getResultList();
verify(result.size() == 2, "wrong resultcount");
Iterator iter = result.iterator();
while (iter.hasNext()) {
Object entity = iter.next();
verify(em.contains(entity), "entity manager doesn't contain result read inside transaction");
}
env.rollbackTransactionAndClear(em);
} finally {
closeEntityManager(em);
}
}
@Test
public void testIntIsNull() throws SQLException {
init();
JPAEnvironment env = getEnvironment();
EntityManager em = env.getEntityManager();
try {
env.beginTransaction(em);
Project project = new Project(null);
em.persist(project);
final int projectId = project.getId();
env.commitTransactionAndClear(em);
Query query = em.createQuery("select p from Project p where p.name IS NULL");
List result = query.getResultList();
verify(result.size() == 1, "wrong resultcount");
Iterator iter = result.iterator();
while (iter.hasNext()) {
project = (Project) iter.next();
verify(project.getId() == projectId, "wrong project");
}
query = em.createQuery("select distinct p from Project p where p.name IS NULL");
result = query.getResultList();
verify(result.size() == 1, "wrong resultcount");
iter = result.iterator();
while (iter.hasNext()) {
project = (Project) iter.next();
verify(project.getId() == projectId, "wrong project");
}
} finally {
closeEntityManager(em);
}
}
private void verifyComparisonPrepdicateResult(EntityManager em, String txt, int... ids) {
Query query = em.createQuery(txt);
List result = query.getResultList();
Set<Integer> actual = new HashSet<Integer>();
for (Object object : result) {
BasicTypesFieldAccess fa = (BasicTypesFieldAccess) object;
actual.add(fa.getId());
}
Set<Integer> expected = new HashSet<Integer>();
for (int i : ids) {
expected.add(i);
}
verify(expected.equals(actual), "expecetd and actual sets are different for query >>" + txt + "<<");
}
@Test
public void testComparisonPrepdicate() throws SQLException {
init();
JPAEnvironment env = getEnvironment();
EntityManager em = env.getEntityManager();
try {
env.beginTransaction(em);
BasicTypesFieldAccess fa = new BasicTypesFieldAccess(17);
fa.setPrimitiveInt(17);
em.persist(fa);
fa = new BasicTypesFieldAccess(18);
fa.setPrimitiveInt(18);
em.persist(fa);
fa = new BasicTypesFieldAccess(19);
fa.setPrimitiveInt(19);
em.persist(fa);
fa = new BasicTypesFieldAccess(20);
fa.setPrimitiveInt(20);
em.persist(fa);
env.commitTransactionAndClear(em);
verifyComparisonPrepdicateResult(em, "Select Object(a) from BasicTypesFieldAccess a where a.primitiveInt = 17", 17);
verifyComparisonPrepdicateResult(em, "Select Object(a) from BasicTypesFieldAccess a where a.primitiveInt > 17", 18,
19, 20);
} finally {
closeEntityManager(em);
}
}
@Test
public void testNamedQuery() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
boolean extended = getEnvironment().usesExtendedPC();
try {
Query query = em.createNamedQuery("getDepartmentByName"); // select d from Department d where d.name = ?1
query.setParameter(1, "twenty");
List result = query.getResultList();
Iterator iter = result.iterator();
verify(iter.hasNext(), "row not found");
Department entity = (Department) iter.next();
if (extended) {
verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
} else {
verify(!em.contains(entity), "entity manager contains result read outside transaction");
}
verify(entity.equals(dep20), " got wrong department");
verify(!iter.hasNext(), "too many rows");
} finally {
closeEntityManager(em);
}
}
@Test
@ToBeInvestigated
public void testUndefinedNamedQuery() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
try {
try {
Query query = em.createNamedQuery("Hutzliputz");
query.getResultList();
flop("undefined query created");
} catch (IllegalArgumentException e) {
}
try {
Query query = em.createNamedQuery(null);
query.getResultList();
flop("undefined query created");
} catch (IllegalArgumentException e) {
}
} finally {
closeEntityManager(em);
}
}
@Test
public void testNamedParameter() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
boolean extended = getEnvironment().usesExtendedPC();
try {
Query query = em.createQuery("select d from Department d where d.name = :name");
query.setParameter("name", "twenty");
List result = query.getResultList();
Iterator iter = result.iterator();
verify(iter.hasNext(), "row not found");
Department entity = (Department) iter.next();
if (extended) {
verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
} else {
verify(!em.contains(entity), "entity manager contains result read outside transaction");
}
verify(entity.equals(dep20), " got wrong department");
verify(!iter.hasNext(), "too many rows");
} finally {
closeEntityManager(em);
}
}
@Test
public void testWrongParameter() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
try {
try {
Query query = em.createQuery("select d from Department d where d.name = :name");
query.setParameter(1, "twenty");
query.getResultList();
flop("missing exception");
} catch (RuntimeException e) {
}
} finally {
closeEntityManager(em);
}
}
@Test
public void testCachedQueryWithClear() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
try {
Query query = em.createNamedQuery("getDepartmentCached");
query.setParameter(1, "twenty");
List<Department> result = query.getResultList();
verify(result.size() == 1, "wrong result size");
em.clear();
result = query.getResultList();
verify(result.size() == 1, "wrong result size");
} finally {
closeEntityManager(em);
}
}
@Test
public void testCachedQueryWithoutClear() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
try {
Query query = em.createNamedQuery("getDepartmentCached");
query.setParameter(1, "twenty");
List<Department> result = query.getResultList();
verify(result.size() == 1, "wrong result size");
result = query.getResultList();
verify(result.size() == 1, "wrong result size");
} finally {
closeEntityManager(em);
}
}
@Test
public void testUnCachedQuery() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
try {
Query query = em.createNamedQuery("getDepartmentUnCached");
query.setParameter(1, "twenty");
List<Department> result = query.getResultList();
verify(result.size() == 1, "wrong result size");
result = query.getResultList();
verify(result.size() == 1, "wrong result size");
} finally {
closeEntityManager(em);
}
}
@Test
@ToBeInvestigated
public void testQueryStringNotValid() throws SQLException {
// TODO enable test as soon as functionality is implemented
init();
EntityManager em = getEnvironment().getEntityManager();
try {
boolean caught = false;
Query query;
try {
query = em.createQuery("this is not a valid query");
try {
query.getResultList();
} catch (PersistenceException ex) {
caught = true;
}
} catch (IllegalArgumentException e) {
caught = true;
}
verify(caught,
"illegal query threw neither IllegalArgumentExceptionon create nor PersistenceException on getResultList");
caught = false;
try {
query = em.createQuery((String) null);
try {
query.getResultList();
} catch (PersistenceException ex) {
caught = true;
}
} catch (IllegalArgumentException e) {
caught = true;
}
verify(caught,
"null query threw neither IllegalArgumentExceptionon create nor PersistenceException on getResultList");
} finally {
closeEntityManager(em);
}
}
@Test
public void testExecuteQueryMultipleTimesWithSameParameter() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
boolean extended = getEnvironment().usesExtendedPC();
try {
Query query = em.createQuery("select d from Department d where d.name = :name");
query.setParameter("name", "twenty");
List result = query.getResultList();
result = query.getResultList();
Iterator iter = result.iterator();
verify(iter.hasNext(), "row not found");
Department entity = (Department) iter.next();
if (extended) {
verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
} else {
verify(!em.contains(entity), "entity manager contains result read outside transaction");
}
verify(entity.equals(dep20), " got wrong department");
verify(!iter.hasNext(), "too many rows");
} finally {
closeEntityManager(em);
}
}
@Test
public void testExecuteQueryMultipleTimesWithDifferentParameter() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
boolean extended = getEnvironment().usesExtendedPC();
try {
Query query = em.createQuery("select d from Department d where d.name = ?1 and d.id = ?2");
query.setParameter(1, "twenty");
query.setParameter(2, 20);
List result = query.getResultList();
Iterator iter = result.iterator();
verify(iter.hasNext(), "row not found");
Department entity = (Department) iter.next();
if (extended) {
verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
} else {
verify(!em.contains(entity), "entity manager contains result read outside transaction");
}
verify(entity.equals(dep20), " got wrong department");
verify(!iter.hasNext(), "too many rows");
query.setParameter(1, "ten");
query.setParameter(2, 10);
result = query.getResultList();
iter = result.iterator();
verify(iter.hasNext(), "row not found");
entity = (Department) iter.next();
if (extended) {
verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
} else {
verify(!em.contains(entity), "entity manager contains result read outside transaction");
}
verify(entity.equals(dep10), " got wrong department");
verify(!iter.hasNext(), "too many rows");
} finally {
closeEntityManager(em);
}
}
@Test
public void testSingleResultOk() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
boolean extended = getEnvironment().usesExtendedPC();
try {
Query query = em.createQuery("select d from Department d where d.name = :name");
query.setParameter("name", "twenty");
Object entity = query.getSingleResult();
if (extended) {
verify(em.contains(entity), "entity manager doesn't contain result read outside transaction");
} else {
verify(!em.contains(entity), "entity manager contains result read outside transaction");
}
verify(entity.equals(dep20), " got wrong department");
} finally {
closeEntityManager(em);
}
}
@Test
public void testNoResult() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
try {
Query query = em.createQuery("select d from Department d where d.name = :name");
query.setParameter("name", "hutzliputz");
try {
query.getSingleResult();
flop("missing NoResultException");
} catch (NoResultException e) {
}
} finally {
closeEntityManager(em);
}
}
@Test
public void testNonUniqueResult() throws SQLException {
init();
EntityManager em = getEnvironment().getEntityManager();
try {
Query query = em.createQuery("select d from Department d");
try {
query.getSingleResult();
flop("missing NonUniqueResultException");
} catch (NonUniqueResultException e) {
}
} finally {
closeEntityManager(em);
}
}
@Test
public void testQueryWithFlush() throws SQLException {
clearAllTables();
JPAEnvironment env = getEnvironment();
EntityManager em = env.getEntityManager();
try {
env.beginTransaction(em);
em.persist(dep10);
env.commitTransactionAndClear(em);
env.beginTransaction(em);
Department dep = em.find(Department.class, 10);
dep.setName("newName");
em.flush();
Query query = em.createQuery("select d from Department d where d.name = :name");
query.setParameter("name", "newName");
Department entity = (Department) query.getSingleResult();
verify(entity.getName().equals("newName"), " wrong department name");
env.commitTransactionAndClear(em);
} finally {
closeEntityManager(em);
}
}
private static boolean hasGetmaxRowsMethod() {
try {
return Query.class.getMethod("getMaxResults") != null;
} catch (NoSuchMethodException e) {
return false;
}
}
private void verifyRowCount(Query query, int maxRows, int startPos, int expected) throws SecurityException, NoSuchMethodException {
query.setMaxResults(maxRows);
query.setFirstResult(startPos);
if (hasGetmaxRowsMethod()) {
assertEquals(query.getMaxResults(), maxRows);
assertEquals(query.getFirstResult(), startPos);
}
int count = query.getResultList().size();
verify(count == expected, "wrong row count: " + count);
if (hasGetmaxRowsMethod()) {
assertEquals(query.getMaxResults(), maxRows);
assertEquals(query.getFirstResult(), startPos);
}
}
@Test
public void testMaxResult() throws SQLException, SecurityException, NoSuchMethodException {
clearAllTables();
JPAEnvironment env = getEnvironment();
EntityManager em = env.getEntityManager();
try {
env.beginTransaction(em);
for (int i = 0; i < 10; i++) {
em.persist(new Project("P" + i));
}
env.commitTransaction(em);
em.clear();
Query query = em.createQuery("select p from Project p");
verifyRowCount(query, 5, 0, 5);
verifyRowCount(query, 10, 0, 10);
verifyRowCount(query, 15, 0, 10);
verifyRowCount(query, 5, 5, 5);
verifyRowCount(query, 10, 5, 5);
verifyRowCount(query, 15, 5, 5);
verifyRowCount(query, 5, 7, 3);
verifyRowCount(query, 10, 7, 3);
verifyRowCount(query, 15, 7, 3);
} finally {
closeEntityManager(em);
}
}
@Test
public void testMaxResultUnlimited() throws SQLException, SecurityException, NoSuchMethodException {
clearAllTables();
JPAEnvironment env = getEnvironment();
EntityManager em = env.getEntityManager();
try {
env.beginTransaction(em);
for (int i = 0; i < 10; i++) {
em.persist(new Project("P" + i));
}
env.commitTransaction(em);
em.clear();
Query query = em.createQuery("select p from Project p");
verifyRowCount(query, Integer.MAX_VALUE, 0, 10);
verifyRowCount(query, Integer.MAX_VALUE, 5, 5);
verifyRowCount(query, Integer.MAX_VALUE, 7, 3);
} finally {
closeEntityManager(em);
}
}
@Test
public void testPagingDefaults() throws SQLException {
if (!hasGetmaxRowsMethod()) {
return;
}
JPAEnvironment env = getEnvironment();
EntityManager em = env.getEntityManager();
try {
Query query = em.createQuery("select p from Project p");
assertEquals(0, query.getFirstResult());
assertEquals(Integer.MAX_VALUE, query.getMaxResults());
} finally {
closeEntityManager(em);
}
}
@Test
public void testFlushMode() throws SQLException {
testFlushMode(AUTO, null);
testFlushMode(AUTO, AUTO);
testFlushMode(AUTO, COMMIT);
testFlushMode(COMMIT, null);
testFlushMode(COMMIT, AUTO);
testFlushMode(COMMIT, COMMIT);
}
private void testFlushMode(FlushModeType flushModeEM, FlushModeType flushModeQuery) throws SQLException {
init();
JPAEnvironment env = getEnvironment();
EntityManager em = env.getEntityManager();
try {
env.beginTransaction(em);
Query query = em.createQuery("select d from Department d where d.name = 'updated'");
if (flushModeEM == COMMIT) {
em.setFlushMode(COMMIT);
}
verify(em.getFlushMode() == flushModeEM, "wrong flushMode");
if (flushModeQuery != null) {
query.setFlushMode(flushModeQuery);
}
boolean flushExpected = isFlushExpected(flushModeEM, flushModeQuery);
Department dep = em.find(Department.class, 10);
dep.setName("updated");
List result = query.getResultList();
if (flushExpected) {
verify(result.size() == 1, "wrong number of rows: " + result.size());
} else {
verify(result.size() == 0, "wrong number of rows: " + result.size());
}
env.commitTransaction(em);
} finally {
closeEntityManager(em);
}
}
private boolean isFlushExpected(FlushModeType flushModeEM, FlushModeType flushModeQuery) {
if (flushModeQuery == null) {
if (flushModeEM == COMMIT) {
return false;
} else {
return true;
}
} else if (flushModeQuery == COMMIT) {
return false;
} else if (flushModeQuery == AUTO) {
return true;
}
throw new IllegalArgumentException("Illegal flushMode(s): flushModeEM = " + flushModeEM + ", flushModeQuery = "
+ flushModeQuery);
}
@Test
public void testTransactionBoundaries() throws SQLException {
init();
JPAEnvironment env = getEnvironment();
EntityManager em = env.getEntityManager();
boolean extended = env.usesExtendedPC();
boolean failureExpected = false;
if (!extended) {
failureExpected = true;
}
try {
// create query outside transaction
Query query = em.createQuery("select d from Department d where d.name = :name");
query.setParameter("name", "twenty");
List result = query.getResultList();
verify(result.size() == 1, "wrong number of rows: " + result.size());
verify(result.get(0).equals(dep20), "got wrong department");
// execute again
result = query.getResultList();
verify(result.size() == 1, "wrong number of rows: " + result.size());
verify(result.get(0).equals(dep20), "got wrong department");
// execute inside transaction
env.beginTransaction(em);
try {
result = query.getResultList();
verify(result.size() == 1, "wrong number of rows: " + result.size());
verify(result.get(0).equals(dep20), "got wrong department");
} catch (PersistenceException e) {
if (!failureExpected) {
throw e;
}
}
env.rollbackTransaction(em);
// create query inside transaction
env.beginTransaction(em);
query = em.createQuery("select d from Department d where d.name = :name");
query.setParameter("name", "twenty");
result = query.getResultList();
verify(result.size() == 1, "wrong number of rows: " + result.size());
verify(result.get(0).equals(dep20), "got wrong department");
env.commitTransaction(em);
// execute outside transaction
try {
result = query.getResultList();
verify(result.size() == 1, "wrong number of rows: " + result.size());
verify(result.get(0).equals(dep20), "got wrong department");
} catch (IllegalStateException e) {
if (!failureExpected) {
throw e;
}
}
// execute inside new transaction
env.beginTransaction(em);
try {
result = query.getResultList();
verify(result.size() == 1, "wrong number of rows: " + result.size());
verify(result.get(0).equals(dep20), "got wrong department");
} catch (IllegalStateException e) {
if (!failureExpected) {
throw e;
}
}
env.rollbackTransaction(em);
} finally {
closeEntityManager(em);
}
}
@Test
public void testBooleanParameter() {
EntityManager em = getEnvironment().getEntityManager();
JPAEnvironment env = getEnvironment();
try {
env.beginTransaction(em);
BasicTypesFieldAccess fieldAccess = new BasicTypesFieldAccess();
fieldAccess.setId(1);
fieldAccess.setPrimitiveBoolean(true);
em.persist(fieldAccess);
fieldAccess = new BasicTypesFieldAccess();
fieldAccess.setId(2);
fieldAccess.setPrimitiveBoolean(false);
em.persist(fieldAccess);
env.commitTransactionAndClear(em);
Query query = em.createQuery("select b from BasicTypesFieldAccess b where b.primitiveBoolean = ?1");
query.setParameter(1, Boolean.TRUE);
List list = query.getResultList();
Iterator iterator = list.iterator();
verify(iterator.hasNext(), "no rows");
BasicTypesFieldAccess value = (BasicTypesFieldAccess) iterator.next();
verify(value.getId() == 1, "wrong id: " + value.getId());
verify(!iterator.hasNext(), "too many rows");
} finally {
closeEntityManager(em);
}
}
}