/******************************************************************************* * 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * SAP - initial API and implementation ******************************************************************************/ package org.eclipse.persistence.testing.tests.wdf.jpa1.query; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; import java.util.Set; import javax.persistence.EntityManager; import javax.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.Bicycle; import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department; import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Employee; import org.eclipse.persistence.testing.models.wdf.jpa1.employee.EmploymentPeriod; import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Hobby; import org.eclipse.persistence.testing.models.wdf.jpa1.employee.MotorVehicle; import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base; import org.junit.Test; public class TestExtendedQueries extends JPA1Base { // the random generator will use this final seed in order to enable reproduceable testing private static final long RANDOM_SEED = 1232133213; // should not be changed private static final int NUMBER_OF_DEPARTMENTS = 10; private static final int NUMBER_OF_EMPLOYEES = 100; // number of maximum tries during random distribution private static final int MAX_NUMBER_OF_TRIES = 100; // since there is a one-to-one relationship for vehicle driver this must at least match the number of employees private static final short NUMBER_OF_MOTORVEHICLES = NUMBER_OF_EMPLOYEES; private static final short NUMBER_OF_BICYCLES = 5; // this maps take note of how much entities are used in relationships private static final Map<String, Department> ALL_DEPARTMENTS = new HashMap<String, Department>(); private static final Map<String, Integer> NUMBER_OF_GIVEN_NAMES_USED = new HashMap<String, Integer>(); private static final Map<String, Integer> NUMBER_OF_SURNAMES_USED = new HashMap<String, Integer>(); private static final Map<Short, List<Integer>> BIKES_RIDERS = new HashMap<Short, List<Integer>>(); private static final Map<Short, Integer> MOTORVEHICLES_DRIVERS = new HashMap<Short, Integer>(); private static final Set<String> EMP_HOBBIES = new HashSet<String>(); // an array of given names private static final String[] GIVEN_NAMES = { "Hadmar", "Hagen", "Hakan", "Hakon", "Hannes", "Hanns", "Hans", "Hansj\u00f6rg", "Hansklaus", "Hanspeter", "Harald", "Harold", "Harro", "Harry", "Hartmut", "Hartwig", "Hartwin", "Harvey", "Hasso", "Hauke", "H\u00e4nel", "Heiko", "Heyko", "Heimo", "Hein", "Heiner", "Heinrich", "Heinz", "Helge", "Helmar", "Helmut", "Hendrik", "Henning", "Henri", "Henrik", "Henryk", "Herbert", "Heribert", "Hermann", "Hieronymus", "Hilarius", "Hilmar", "Hinrich", "Hjalmar", "Holger", "Horst", "Hubert", "Hubertus", "Hugo", "Humphrey", "Hanna", "Hannah", "Hannelore", "Harriet", "Hedi", "Hedwig", "Heide", "Heidemarie", "Heidi", "Heike", "Heinke", "Helen", "Helena", "Helene", "Helga", "Helgard", "Hella", "Helma", "Henrike", "Herma", "Hermine", "Hertha", "Hieu", "Hilda", "Hilde", "Hildegard", "Hilke", "Hulda", "Holde", "Holda", "Hedda", "Heida", "Hazel" }; // an array of surnames private static final String[] SURNAMES = { "Haak", "Haas", "Habermann", "Hache", "Hackmann", "Halbach", "Haller", "Hamann", "Hamburger", "Hamilton", "Hampe", "Hanisch", "Hanson", "Hanstein", "Hardenberg", "Harding", "Hardy", "Harnack", "Hartenthaler", "Hartfelder", "Hartig", "Hary", "Haus Lancaster", "Hausmann", "Hausner", "Havenstein", "Hawke", "Hayek", "Hecht", "Heer", "Hegemann", "Heidegger", "Heider", "Heim", "Hein", "Heinichen", "Heinrich", "Heise", "Helbig", "Hellmann", "Helmig", "Helms", "Hemsterhuis", "Hendrix", "Hennig", "Henning", "Henry", "Henschel", "Hense", "Hentschel", "Herbst", "Herder", "Hermann", "Hermelink", "Herold", "Herrmann", "Herzog", "Hesse", "Hesselbarth", "Hettner", "Heuser", "Hewitt", "Hilbert", "Hildebrand", "Hildebrandt", "Hilgenfeld" }; // list of hobbienames private static final String[] HOBBY_NAMES = { "reading", "cooking", "watching tv", "cleaning the house", "swimming", "computers", "stamps" }; // array of all hobbies private static final Hobby[] HOBBIES = new Hobby[HOBBY_NAMES.length]; // array of all bicycles private static final Bicycle[] BICYCLES = new Bicycle[NUMBER_OF_BICYCLES]; // array of all motorvehicles private static final MotorVehicle[] MOTORVEHICLES = new MotorVehicle[NUMBER_OF_MOTORVEHICLES]; // randomizer for distributing relationships between Employees and other entities private static final Random nameRandomizer = new Random(RANDOM_SEED); protected void resetData() { NUMBER_OF_GIVEN_NAMES_USED.clear(); NUMBER_OF_SURNAMES_USED.clear(); EMP_HOBBIES.clear(); MOTORVEHICLES_DRIVERS.clear(); } protected String getRandomSurname() { String tmpName = SURNAMES[nameRandomizer.nextInt(SURNAMES.length)]; if (!NUMBER_OF_SURNAMES_USED.containsKey(tmpName)) { NUMBER_OF_SURNAMES_USED.put(tmpName, new Integer(1)); } else { Integer tmpNum = NUMBER_OF_SURNAMES_USED.get(tmpName); tmpNum = Integer.valueOf(tmpNum.intValue() + 1); NUMBER_OF_SURNAMES_USED.put(tmpName, tmpNum); } return tmpName; } protected String getRandomGivenName() { String tmpName = GIVEN_NAMES[nameRandomizer.nextInt(GIVEN_NAMES.length)]; if (!NUMBER_OF_GIVEN_NAMES_USED.containsKey(tmpName)) { NUMBER_OF_GIVEN_NAMES_USED.put(tmpName, new Integer(1)); } else { Integer tmpNum = NUMBER_OF_GIVEN_NAMES_USED.get(tmpName); tmpNum = Integer.valueOf(tmpNum.intValue() + 1); NUMBER_OF_GIVEN_NAMES_USED.put(tmpName, tmpNum); } return tmpName; } /** * returns a hobby for given employee, it is not possible to assign a hobby more than once to a employee * * @param empID * the ID of the employee * @return a hobby for the given employee ID * @throws Exception * is thrown if there are no hobbies left which have not already been assigned to this employee */ protected Hobby getRandomHobby(int empID) { boolean matched = false; int index = 0; for (int number_of_tries = 0; !matched; number_of_tries++) { index = nameRandomizer.nextInt(HOBBIES.length - 1); if (!EMP_HOBBIES.contains(empID + "_" + index)) { EMP_HOBBIES.add(empID + "_" + index); matched = true; } if (number_of_tries >= MAX_NUMBER_OF_TRIES) { throw new RuntimeException("Can't find anymore randomly distributed hobbies"); } } return HOBBIES[index]; } @SuppressWarnings("boxing") protected Bicycle getRandomBike(int empID) { short index = (short) nameRandomizer.nextInt(BICYCLES.length - 1); // take a note about this relation if (!BIKES_RIDERS.containsKey(BICYCLES[index].getId())) { ArrayList<Integer> tmpAl = new ArrayList<Integer>(); tmpAl.add(empID); BIKES_RIDERS.put(BICYCLES[index].getId(), tmpAl); } else { List<Integer> tmpAl = BIKES_RIDERS.get(BICYCLES[index].getId()); tmpAl.add(empID); } return BICYCLES[index]; } @SuppressWarnings("boxing") protected MotorVehicle getRandomMotorVehicle(int empID) { // take note about this relation boolean matched = false; short index = 0; for (int number_of_tries = 0; !matched; number_of_tries++) { index = (short) nameRandomizer.nextInt(MOTORVEHICLES.length - 1); if (!MOTORVEHICLES_DRIVERS.containsKey(MOTORVEHICLES[index].getId())) { MOTORVEHICLES_DRIVERS.put(MOTORVEHICLES[index].getId(), empID); matched = true; } if (number_of_tries >= MAX_NUMBER_OF_TRIES) { throw new RuntimeException("Can't find anymore randomly distributed motorvehicles"); } } return MOTORVEHICLES[index]; } @Override protected void setup() { resetData(); JPAEnvironment env = getEnvironment(); EntityManager em = env.getEntityManager(); try { env.beginTransaction(em); // fills the hobby-array for (int i = 0; i < HOBBY_NAMES.length; i++) { Hobby aHobby = new Hobby(HOBBY_NAMES[i]); HOBBIES[i] = aHobby; em.persist(aHobby); } // creates & persists some departments for (int i = 0; i < NUMBER_OF_DEPARTMENTS; i++) { Department tmpDep = new Department(i, "Department_" + i); // ALL_DEPARTMENTS.put(tmpDep.getName(), tmpDep); em.persist(tmpDep); } // creates & persists some motorvehicles for (int i = 0; i < NUMBER_OF_MOTORVEHICLES; i++) { MotorVehicle tmpMVehicle = new MotorVehicle(); tmpMVehicle.setBrand("foo-car"); MOTORVEHICLES[i] = tmpMVehicle; em.persist(tmpMVehicle); } // creates & persists some bicycles for (int i = 0; i < NUMBER_OF_BICYCLES; i++) { Bicycle tmpBike = new Bicycle(); tmpBike.setBrand("foo-brand"); tmpBike.setRiders(new ArrayList<Employee>()); BICYCLES[i] = tmpBike; em.persist(tmpBike); } // creates & persists some empoyees for (int i = 0; i < NUMBER_OF_EMPLOYEES; i++) { /* * sets a department tries to set 10 employees to each department example: employees 1 to 10 are related to * department 1. employees 11 to 20 are mapped to department 2 and so on */ Employee tmpEmp = new Employee(i, this.getRandomGivenName(), this.getRandomSurname(), ALL_DEPARTMENTS .get("Department_" + Math.ceil(i / 100) * 10)); // add two hobbies tmpEmp.addHobby(this.getRandomHobby(tmpEmp.getId())); tmpEmp.addHobby(this.getRandomHobby(tmpEmp.getId())); tmpEmp.addHobby(this.getRandomHobby(tmpEmp.getId())); tmpEmp.addHobby(this.getRandomHobby(tmpEmp.getId())); tmpEmp.addHobby(this.getRandomHobby(tmpEmp.getId())); // every second employee gets a motorvehicle if (i % 2 == 0) { getRandomMotorVehicle(tmpEmp.getId()).setDriver(tmpEmp); } // the others get a bicycle else { getRandomBike(tmpEmp.getId()).getRiders().add(tmpEmp); } // set the period tmpEmp.setEmploymentPeriod(new EmploymentPeriod()); tmpEmp.getEmploymentPeriod().setStartDate(new Date(System.currentTimeMillis() - 1000000000)); tmpEmp.getEmploymentPeriod().setEndDate(new Date(System.currentTimeMillis() + 1000000000)); em.persist(tmpEmp); } env.commitTransactionAndClear(em); // em.clear(); } finally { closeEntityManager(em); } } /* * @Test public void testQueryWithMemberOf() throws Exception { EntityManager em = getEnvironment().getEntityManager(); try * { Bicycle bike = new Bicycle(); bike.setId((short)12); bike.setBrand("foo"); bike.setColor("brown"); * bike.setNumberOfGears((short)1); em.persist(bike); * * //test string-mapping of enums Query query = em.createQuery("Select Distinct Object(emp) FROM Employee emp WHERE :param * NOT MEMBER emp.bicycles"); query.setParameter("param", bike); query.getResultList(); } finally { closeEntityManager(em); * } } */ // @TestProperties(unsupportedDatabaseVendors = { DatabaseVendor.OPEN_SQL }) @Test public void testQueryWithUpdateAndSet() throws Exception { JPAEnvironment env = getEnvironment(); EntityManager em = env.getEntityManager(); try { env.beginTransaction(em); Query query = em .createQuery("UPDATE Employee emp SET emp.salary = emp.salary + :param1 WHERE emp.firstname = SUBSTRING(:string, :int1, :int2)"); query.setParameter("param1", Integer.valueOf(13)); query.setParameter("string", "moo"); query.setParameter("int1", Integer.valueOf(1)); query.setParameter("int2", Integer.valueOf(2)); query.executeUpdate(); env.commitTransaction(em); } finally { closeEntityManager(em); } } // @TestProperties(unsupportedDatabaseVendors = { DatabaseVendor.OPEN_SQL }) @Test public void testQueryWithBuiltinAbs() throws Exception { EntityManager em = getEnvironment().getEntityManager(); try { // test string-mapping of enums Query query = em.createQuery("Select DISTINCT Object(emp) From Employee emp WHERE emp.salary > ABS(:dbl)"); query.setParameter("dbl", new Double(1180D)); query.getResultList(); } finally { closeEntityManager(em); } } // @TestProperties(unsupportedDatabaseVendors = { DatabaseVendor.OPEN_SQL }) @Test public void testQueryWithMemberOf() throws Exception { EntityManager em = getEnvironment().getEntityManager(); try { // test string-mapping of enums Query query = em .createQuery("Select Distinct Object(emp) FROM Employee emp WHERE emp.firstname = SUBSTRING(:string, :int1, :int2)"); query.setParameter("string", "moo"); query.setParameter("int1", Integer.valueOf(1)); query.setParameter("int2", Integer.valueOf(2)); query.getResultList(); } finally { closeEntityManager(em); } } @Test public void testQueryWithComparisonExpressionAndEnums() throws Exception { EntityManager em = getEnvironment().getEntityManager(); try { // test string-mapping of enums Query query4 = em .createQuery("SELECT btfa.id FROM BasicTypesFieldAccess btfa WHERE btfa.enumString = org.eclipse.persistence.testing.models.wdf.jpa1.types.UserDefinedEnum.HUGO"); query4.getResultList(); // test ordinal-mapping of enums Query query5 = em .createQuery("SELECT btfa.id FROM BasicTypesFieldAccess btfa WHERE btfa.enumOrdinal = org.eclipse.persistence.testing.models.wdf.jpa1.types.UserDefinedEnum.HUGO"); query5.getResultList(); } finally { closeEntityManager(em); } } @ToBeInvestigated @Test public void testQueryWithInExpressionAndEnums() throws Exception { EntityManager em = getEnvironment().getEntityManager(); try { // test string-mapping of enums Query query4 = em .createQuery("SELECT btfa.id FROM BasicTypesFieldAccess btfa WHERE btfa.enumString IN (org.eclipse.persistence.testing.models.wdf.jpa1.types.UserDefinedEnum.HUGO, org.eclipse.persistence.testing.models.wdf.jpa1.types.UserDefinedEnum.EMIL)"); query4.getResultList(); // test ordinal-mapping of enums Query query5 = em .createQuery("SELECT btfa.id FROM BasicTypesFieldAccess btfa WHERE btfa.enumOrdinal IN (com.sap.jpa.example.UserDefinedEnum.HUGO, com.sap.jpa.example.UserDefinedEnum.EMIL)"); query5.getResultList(); } finally { closeEntityManager(em); } } @Test public void testQueryWithAggregateWithHavingExpression() throws Exception { EntityManager em = getEnvironment().getEntityManager(); try { // this one tests aggregate expression in having condition Query query2 = em .createQuery("SELECT e.firstname FROM Employee e JOIN e.hobbies h GROUP BY e.firstname HAVING COUNT(DISTINCT e.id) = 1"); query2.getResultList(); } finally { closeEntityManager(em); } } @Test public void testQueryWithInExpressionAndParameters() throws Exception { EntityManager em = getEnvironment().getEntityManager(); try { // this one tests for the IN predicate in combination with two parameters Query query1 = em.createQuery("select e.id from Employee e where e.id IN (?1, ?2)"); query1.setParameter(1, Integer.valueOf(1)); query1.setParameter(2, Integer.valueOf(2)); query1.getResultList(); } finally { closeEntityManager(em); } } @SuppressWarnings("unchecked") @Test public void testBasicQuery() { EntityManager em = getEnvironment().getEntityManager(); try { Query query = em.createQuery("select e from Employee e"); List result = query.getResultList(); verify(result.size() == NUMBER_OF_EMPLOYEES, "wrong resultcount for employees"); } finally { closeEntityManager(em); } } /** * check for a thrown exception in case of an illegal OrderBy-clause */ @ToBeInvestigated @Test public void testInvalidOrderBy() { boolean passed = false; EntityManager em = getEnvironment().getEntityManager(); try { em.createQuery("SELECT e.firstname FROM Employee e ORDER BY e.salary"); } catch (IllegalArgumentException iAEx) { passed = true; } finally { closeEntityManager(em); } verify(passed, "missing IllegalArgumentException"); } /** * check for a thrown exception in case of an illegal OrderBy-clause */ @ToBeInvestigated @Test public void testInvalidOrderByWithCmr() { boolean passed = false; EntityManager em = getEnvironment().getEntityManager(); try { em.createQuery("SELECT e.department.name FROM Employee e ORDER BY e.department.id"); } catch (IllegalArgumentException iAEx) { passed = true; } finally { closeEntityManager(em); } verify(passed, "missing IllegalArgumentException"); } @Test public void testOrderBy() { EntityManager em = getEnvironment().getEntityManager(); try { em.createQuery("SELECT e FROM Employee e ORDER BY e.salary ASC, e.firstname DESC, e.lastname DESC"); } finally { closeEntityManager(em); } } @Test public void testOrderByCmr() { EntityManager em = getEnvironment().getEntityManager(); try { em.createQuery("SELECT e.department FROM Employee e ORDER BY e.department.id ASC"); } finally { closeEntityManager(em); } } /** * check for the right occurence of all names in the result of the query */ @SuppressWarnings("unchecked") @Test public void testSurnamesOfEmployees() { EntityManager em = getEnvironment().getEntityManager(); try { Query query = em.createQuery("SELECT e from Employee e WHERE e.lastname=?1"); Iterator<String> iter = NUMBER_OF_SURNAMES_USED.keySet().iterator(); while (iter.hasNext()) { String surname = iter.next(); Integer surnamesUsed = NUMBER_OF_SURNAMES_USED.get(surname); query.setParameter(1, surname); List result = query.getResultList(); verify(result.size() == surnamesUsed.intValue(), "the number of persons with given name " + surname + " in the result does not match the number of names used when the entities where created."); } } finally { closeEntityManager(em); } } @SuppressWarnings("unchecked") @Test public void testGivenNamesOfEmployees() { EntityManager em = getEnvironment().getEntityManager(); try { Query query = em.createQuery("SELECT e from Employee e WHERE e.firstname=?1"); Iterator<String> iter = NUMBER_OF_GIVEN_NAMES_USED.keySet().iterator(); while (iter.hasNext()) { String givenName = iter.next(); Integer givenNamesUsed = NUMBER_OF_GIVEN_NAMES_USED.get(givenName); query.setParameter(1, givenName); List result = query.getResultList(); verify(result.size() == givenNamesUsed.intValue(), "the number of persons with given name " + givenName + " in the result does not match the number of names used when the entities where created."); } } finally { closeEntityManager(em); } } @SuppressWarnings("unchecked") @Test public void testNumberOfDrivers() { EntityManager em = getEnvironment().getEntityManager(); try { Query query = em.createQuery("SELECT d.firstname FROM MotorVehicle mv JOIN mv.driver d WHERE mv.id = ?1"); Iterator<Short> iter = MOTORVEHICLES_DRIVERS.keySet().iterator(); while (iter.hasNext()) { Short vehicleID = iter.next(); // can only be 1 since the one-to-one relationship for drivers int numberOfDrivers = 1; query.setParameter(1, vehicleID); List result = query.getResultList(); verify(result.size() == numberOfDrivers, "the number of drivers for motorvehicle does not match " + result.size() + " != " + numberOfDrivers); } } finally { closeEntityManager(em); } } @SuppressWarnings("unchecked") @Test public void testNumberOfDrivenVehicles() { EntityManager em = getEnvironment().getEntityManager(); try { Query query = em.createQuery("SELECT d.firstname FROM MotorVehicle mv JOIN mv.driver d"); List result = query.getResultList(); verify(result.size() == MOTORVEHICLES_DRIVERS.size(), "there number of driver-relationships between "); } finally { closeEntityManager(em); } } }