/******************************************************************************* * Copyright (c) 1998, 2015 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 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: * Oracle - initial API and implementation from Oracle TopLink * 04/29/2011 - 2.3 Andrei Ilitchev * - Bug 328404 - JPA Persistence Unit Composition * Adapted org.eclipse.persistence.testing.tests.jpa.xml.advanced.EntityMappingsAdvancedJUnitTestCase * for composite persistence unit. * Try to keep one-to-one correspondence between the two in the future, too. * The tests that could not (or not yet) adapted for composite persistence unit * are commented out, the quick explanation why the test can't run is provided. ******************************************************************************/ package org.eclipse.persistence.testing.tests.jpa.xml.composite.advanced; import java.lang.reflect.Array; import java.sql.Date; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import java.util.Vector; import javax.persistence.Query; import javax.persistence.EntityManager; import javax.persistence.EntityNotFoundException; import junit.framework.*; import org.eclipse.persistence.config.QueryHints; import org.eclipse.persistence.descriptors.ClassDescriptor; import org.eclipse.persistence.descriptors.SelectedFieldsLockingPolicy; import org.eclipse.persistence.descriptors.invalidation.CacheInvalidationPolicy; import org.eclipse.persistence.descriptors.invalidation.TimeToLiveCacheInvalidationPolicy; import org.eclipse.persistence.internal.descriptors.OptimisticLockingPolicy; import org.eclipse.persistence.internal.helper.ClassConstants; import org.eclipse.persistence.internal.helper.DatabaseField; import org.eclipse.persistence.internal.helper.Helper; import org.eclipse.persistence.internal.sessions.DatabaseSessionImpl; import org.eclipse.persistence.mappings.DatabaseMapping; import org.eclipse.persistence.mappings.DirectToFieldMapping; import org.eclipse.persistence.mappings.ForeignReferenceMapping; import org.eclipse.persistence.mappings.converters.ObjectTypeConverter; import org.eclipse.persistence.queries.DoesExistQuery; import org.eclipse.persistence.sessions.broker.SessionBroker; import org.eclipse.persistence.sessions.server.ServerSession; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.EmployeePopulator; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.ModelExamples; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_1.Address; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_1.AdvancedTableCreator_1; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_1.Bungalow; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_1.Customer; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_2.AdvancedTableCreator_2; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_2.Employee; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_2.EmploymentPeriod; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_3.AdvancedTableCreator_3; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_3.Dealer; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_3.LargeProject; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_3.PhoneNumber; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_3.Project; import org.eclipse.persistence.testing.models.jpa.xml.composite.advanced.member_3.SmallProject; /*import org.eclipse.persistence.testing.models.jpa.xml.advanced.Confidant; import org.eclipse.persistence.testing.models.jpa.xml.advanced.Loner; import org.eclipse.persistence.testing.models.jpa.xml.advanced.Name; import org.eclipse.persistence.testing.models.jpa.xml.advanced.ReadOnlyClass; import org.eclipse.persistence.testing.models.jpa.xml.advanced.Shovel; import org.eclipse.persistence.testing.models.jpa.xml.advanced.ShovelDigger; import org.eclipse.persistence.testing.models.jpa.xml.advanced.ShovelOwner; import org.eclipse.persistence.testing.models.jpa.xml.advanced.ShovelProject; import org.eclipse.persistence.testing.models.jpa.xml.advanced.ShovelSections; import org.eclipse.persistence.testing.models.jpa.xml.advanced.SmallProject; import org.eclipse.persistence.testing.models.jpa.xml.advanced.ShovelSections.MaterialType; import org.eclipse.persistence.testing.models.jpa.xml.advanced.Violation; import org.eclipse.persistence.testing.models.jpa.xml.advanced.ViolationCode; import org.eclipse.persistence.testing.models.jpa.xml.advanced.Violation.ViolationID; import org.eclipse.persistence.testing.models.jpa.xml.advanced.ViolationCode.ViolationCodeId; import org.eclipse.persistence.testing.models.jpa.xml.advanced.additionalcriteria.Bolt; import org.eclipse.persistence.testing.models.jpa.xml.advanced.additionalcriteria.Nut; import org.eclipse.persistence.testing.models.jpa.xml.advanced.additionalcriteria.School; import org.eclipse.persistence.testing.models.jpa.xml.advanced.additionalcriteria.Student;*/ import org.eclipse.persistence.testing.framework.JoinedAttributeTestHelper; import org.eclipse.persistence.testing.framework.junit.JUnitTestCase; import org.eclipse.persistence.testing.tests.jpa.TestingProperties; import org.eclipse.persistence.tools.schemaframework.TableCreator; /** * JUnit test case(s) for the TopLink EntityMappingsXMLProcessor. */ public class EntityMappingsAdvancedJUnitTestCase extends JUnitTestCase { private static Integer employeeId, extendedEmployeeId; private static long visa = 1234567890; private static long amex = 1987654321; private static long diners = 1192837465; private static long mastercard = 1647382910; private static long rbc = 4783; private static long scotia = 8732; private static long td = 839362; private static long cibc = 948274; private String m_persistenceUnit; public EntityMappingsAdvancedJUnitTestCase() { super(); } public EntityMappingsAdvancedJUnitTestCase(String name) { super(name); } public EntityMappingsAdvancedJUnitTestCase(String name, String persistenceUnit) { super(name); m_persistenceUnit = persistenceUnit; } public String getPersistenceUnitName() { return m_persistenceUnit; } /* * n is a value between 1 and 3 */ public String getComponentMemberPuName(int n) { return "xml-composite-advanced-member_" + n; } public static Test suite() { String ormTesting = TestingProperties.getProperty(TestingProperties.ORM_TESTING, TestingProperties.JPA_ORM_TESTING); final String persistenceUnit = ormTesting.equals(TestingProperties.JPA_ORM_TESTING)? "xml-composite-advanced" : "xml-extended-composite-advanced"; TestSuite suite = new TestSuite("Advanced Model - " + persistenceUnit); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testSetup", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testCreateEmployee", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testReadEmployee", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testNamedNativeQueryOnAddress", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testNamedQueryOnEmployee", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testUpdateEmployee", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testRefreshNotManagedEmployee", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testRefreshRemovedEmployee", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testDeleteEmployee", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testUnidirectionalPersist", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testUnidirectionalUpdate", persistenceUnit)); // Can't join different data bases suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testUnidirectionalFetchJoin", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testUnidirectionalTargetLocking_AddRemoveTarget", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testUnidirectionalTargetLocking_DeleteSource", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testMustBeCompositeMember")); if (persistenceUnit.equals("xml-extended-composite-advanced")) { suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testSexObjectTypeConverterDefaultValue", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testExistenceCheckingSetting", persistenceUnit)); // suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testReadOnlyClassSetting", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testEmployeeChangeTrackingPolicy", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testAddressChangeTrackingPolicy", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testPhoneNumberChangeTrackingPolicy", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testProjectChangeTrackingPolicy", persistenceUnit)); // Can't join different data bases suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testJoinFetchSetting", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testEmployeeOptimisticLockingSettings", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testEmployeeCacheSettings", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testProjectOptimisticLockingSettings", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testExtendedEmployee", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testGiveExtendedEmployeeASexChange", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testNamedStoredProcedureQuery", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testNamedStoredProcedureQueryInOut", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testMethodBasedTransformationMapping", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testClassBasedTransformationMapping", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testClassInstanceConverter", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testProperty", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testAccessorMethods", persistenceUnit)); suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testIfMultipleBasicCollectionMappingsExistForEmployeeResponsibilites", persistenceUnit)); // These are dynamic persistence tests. // suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testAttributeTypeSpecifications", persistenceUnit)); // suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testMockDynamicClassCRUD", persistenceUnit)); // suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testEnumeratedPrimaryKeys", persistenceUnit)); // suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testAdditionalCriteriaModelPopulate", persistenceUnit)); // suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testAdditionalCriteria", persistenceUnit)); // suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testAdditionalCriteriaWithParameterFromEM1", persistenceUnit)); // suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testAdditionalCriteriaWithParameterFromEM2", persistenceUnit)); // suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testAdditionalCriteriaWithParameterFromEMF", persistenceUnit)); // suite.addTest(new EntityMappingsAdvancedJUnitTestCase("testComplexAdditionalCriteria", persistenceUnit)); } return suite; } /** * The setup is done as a test, both to record its failure, and to allow execution in the server. */ public void testSetup() { SessionBroker broker = getSessionBroker(); // member sessions ServerSession[] sessions = { (ServerSession)broker.getSessionForName(getComponentMemberPuName(1)), (ServerSession)broker.getSessionForName(getComponentMemberPuName(2)), (ServerSession)broker.getSessionForName(getComponentMemberPuName(3)) }; // table creators for each member session TableCreator[] tableCreators = { new AdvancedTableCreator_1(), new AdvancedTableCreator_2(), new AdvancedTableCreator_3() }; for (int i = 0; i < sessions.length; i++) { ServerSession ss = sessions[i]; for (int k = 0; k < tableCreators.length; k++) { TableCreator tableCreator = tableCreators[k]; if (k == i) { tableCreator.replaceTables(ss); } else { if (!usingTheSameDatabase(ss, sessions[k])) { // Drop tables from databases corresponding to the other sessions // so that each table only defined in a single database. // If a wrong session is queried then the query always fails - good for diagnostics. tableCreator.dropTables(ss); } } } // Force uppercase for Postgres. if (ss.getPlatform().isPostgreSQL()) { ss.getLogin().setShouldForceFieldNamesToUpperCase(true); } } // Populate the database with our examples. EmployeePopulator employeePopulator = new EmployeePopulator(); employeePopulator.buildExamples(); employeePopulator.persistExample(broker); clearCache(); } /** * Verifies that access-methods are correctly processed and used. */ public void testAccessorMethods() { EntityManager em = createEntityManager(); String testSin = "123456"; beginTransaction(em); try { Employee employee = ModelExamples.employeeExample1(); employee.enterSIN(testSin); em.persist(employee); Integer employeeId = employee.getId(); commitTransaction(em); clearCache(); em.clear(); // Re-read the employee and verify the data. Employee emp = em.find(Employee.class, employeeId); assertTrue("The SIN value was not persisted.", testSin.equals( emp.returnSIN() ) ); assertTrue("The enterSIN accessor on Employee was not used to set the value", emp.returnSinChangeCounter()==1 ); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } } /** * Test user defined additional criteria with no parameters. */ /* public void testAdditionalCriteriaModelPopulate() { EntityManager em = createEntityManager(); beginTransaction(em); try { // Persist some schools School school1 = new School(); school1.setName("Ottawa Junior High"); school1.addStudent(new Student("OttawaJRStud1")); school1.addStudent(new Student("OttawaJRStud2")); school1.addStudent(new Student("OttawaJRStud3")); em.persist(school1); School school2 = new School(); school2.setName("Ottawa Senior High"); school2.addStudent(new Student("OttawaSRStud1")); school2.addStudent(new Student("OttawaSRStud2")); school2.addStudent(new Student("OttawaSRStud3")); school2.addStudent(new Student("OttawaSRStud4")); school2.addStudent(new Student("OttawaSRStud5")); em.persist(school2); School school3 = new School(); school3.setName("Toronto Junior High"); school3.addStudent(new Student("TorontoJRStud1")); school3.addStudent(new Student("TorontoJRStud2")); school3.addStudent(new Student("TorontoJRStud3")); school3.addStudent(new Student("TorontoJRStud4")); school3.addStudent(new Student("TorontoJRStud5")); school3.addStudent(new Student("TorontoJRStud6")); school3.addStudent(new Student("TorontoJRStud7")); em.persist(school3); School school4 = new School(); school4.setName("Toronto Senior High"); school4.addStudent(new Student("TorontoSRStud1")); school4.addStudent(new Student("TorontoSRStud2")); school4.addStudent(new Student("TorontoSRStud3")); school4.addStudent(new Student("TorontoSRStud4")); school4.addStudent(new Student("TorontoSRStud5")); school4.addStudent(new Student("TorontoSRStud6")); school4.addStudent(new Student("TorontoSRStud7")); school4.addStudent(new Student("TorontoSRStud8")); school4.addStudent(new Student("TorontoSRStud9")); school4.addStudent(new Student("TorontoSRStud10")); school4.addStudent(new Student("TorontoSRStud11")); em.persist(school4); School school5 = new School(); school5.setName("Montreal Senior High"); school5.addStudent(new Student("MontrealSRStud1")); school5.addStudent(new Student("MontrealSRStud2")); school5.addStudent(new Student("MontrealSRStud3")); school5.addStudent(new Student("MontrealSRStud4")); school5.addStudent(new Student("MontrealSRStud5")); em.persist(school5); Bolt bolt1 = new Bolt(); Nut nut1 = new Nut(); nut1.setColor("Grey"); nut1.setSize(8); bolt1.setNut(nut1); em.persist(bolt1); Bolt bolt2 = new Bolt(); Nut nut2 = new Nut(); nut2.setColor("Black"); nut2.setSize(8); bolt2.setNut(nut2); em.persist(bolt2); Bolt bolt3 = new Bolt(); Nut nut3 = new Nut(); nut3.setColor("Grey"); nut3.setSize(6); bolt3.setNut(nut3); em.persist(bolt3); Bolt bolt4 = new Bolt(); Nut nut4 = new Nut(); nut4.setColor("Black"); nut4.setSize(6); bolt4.setNut(nut4); em.persist(bolt4); Bolt bolt5 = new Bolt(); Nut nut5 = new Nut(); nut5.setColor("Grey"); nut5.setSize(2); bolt5.setNut(nut5); em.persist(bolt5); Bolt bolt6 = new Bolt(); Nut nut6 = new Nut(); nut6.setColor("Grey"); nut6.setSize(8); bolt6.setNut(nut6); em.persist(bolt6); commitTransaction(em); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); // Re-throw exception to ensure stacktrace appears in test result. throw e; } closeEntityManager(em); }*/ /** * Test user defined additional criteria with no parameters. The additional * criteria on school filters for Ottawa named schools. */ public void testAdditionalCriteria() { EntityManager em = createEntityManager(); try { List schools = em.createNamedQuery("findJPQLXMLSchools").getResultList(); assertTrue("Incorrect number of schools were returned [" + schools.size() + "], expected [2]", schools.size() == 2); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); // Re-throw exception to ensure stacktrace appears in test result. throw e; } closeEntityManager(em); } /** * Test user defined additional criteria with parameter. */ public void testAdditionalCriteriaWithParameterFromEM1() { EntityManager em = createEntityManager(); try { // This should override the EMF property of Montreal% em.setProperty("NAME", "Ottawa%"); // Find the schools, because of our additional criteria on Student // and the property above, we should only return Ottawa students. List students = em.createQuery("SELECT s from XMLStudent s").getResultList(); assertTrue("Incorrect number of students were returned [" + students.size() + "], expected [8]", students.size() == 8); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); // Re-throw exception to ensure stacktrace appears in test result. throw e; } closeEntityManager(em); } /** * Test user defined additional criteria with parameter. */ public void testAdditionalCriteriaWithParameterFromEM2() { EntityManager em = createEntityManager(); try { // This should override the EMF property of Montreal% em.setProperty("NAME", "Toronto%"); // Find the schools, because of our additional criteria on Student // and the property above, we should only return Toronto students. // However, they should not have any schools loaded. List students = em.createQuery("SELECT s from XMLStudent s").getResultList(); assertTrue("Incorrect number of students were returned [" + students.size() + "], expected [18]", students.size() == 18); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); // Re-throw exception to ensure stacktrace appears in test result. throw e; } closeEntityManager(em); } /** * Test user defined additional criteria with parameters. */ public void testAdditionalCriteriaWithParameterFromEMF() { EntityManager em = createEntityManager(); try { // This should use the EMF NAME property of Montreal% List students = em.createQuery("SELECT s from XMLStudent s").getResultList(); assertTrue("Incorrect number of students were returned [" + students.size() + "], expected [5]", students.size() == 5); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); // Re-throw exception to ensure stacktrace appears in test result. throw e; } closeEntityManager(em); } /** * Test user defined additional criteria with parameter. */ public void testComplexAdditionalCriteria() { EntityManager em = createEntityManager(); try { em.setProperty("NUT_SIZE", 8); em.setProperty("NUT_COLOR", "Grey"); List bolts = em.createQuery("SELECT b from XMLBolt b").getResultList(); assertTrue("Incorrect number of bolts were returned [" + bolts.size() + "], expected [2]", bolts.size() == 2); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); // Re-throw exception to ensure stacktrace appears in test result. throw e; } closeEntityManager(em); } /** * Verifies a default object type value is set from metadata processing. */ public void testSexObjectTypeConverterDefaultValue() { DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor employeeDescriptor = session.getDescriptor(Employee.class); DirectToFieldMapping mapping = (DirectToFieldMapping) employeeDescriptor.getMappingForAttributeName("gender"); assertNotNull("Gender mapping from Employee not found.", mapping); assertTrue("No object type converter found on the gender mapping.", ObjectTypeConverter.class.isAssignableFrom(mapping.getConverter().getClass())); assertTrue("Default object value on the object type converter for gender was not set to Male.", ((ObjectTypeConverter) mapping.getConverter()).getDefaultAttributeValue().equals(Employee.Gender.Male.name())); } /** * Verifies that existence-checking metadata is correctly processed. */ public void testExistenceCheckingSetting() { DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor employeeDescriptor = session.getDescriptor(Employee.class); assertTrue("Employee existence checking was incorrect", employeeDescriptor.getQueryManager().getDoesExistQuery().getExistencePolicy() == DoesExistQuery.CheckDatabase); ClassDescriptor projectDescriptor = session.getDescriptor(Project.class); assertTrue("Project existence checking was incorrect", projectDescriptor.getQueryManager().getDoesExistQuery().getExistencePolicy() == DoesExistQuery.CheckCache); ClassDescriptor smallProjectDescriptor = session.getDescriptor(SmallProject.class); assertTrue("SmallProject existence checking was incorrect", smallProjectDescriptor.getQueryManager().getDoesExistQuery().getExistencePolicy() == DoesExistQuery.AssumeExistence); ClassDescriptor largeProjectDescriptor = session.getDescriptor(LargeProject.class); assertTrue("LargeProject existence checking was incorrect", largeProjectDescriptor.getQueryManager().getDoesExistQuery().getExistencePolicy() == DoesExistQuery.AssumeNonExistence); } /** * Verifies that a basic collection is not added to the employee descriptor * twice. */ public void testIfMultipleBasicCollectionMappingsExistForEmployeeResponsibilites() { DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor employeeDescriptor = session.getDescriptor(Employee.class); int foundCount = 0; for (DatabaseMapping mapping : employeeDescriptor.getMappings()) { if (mapping.isDirectCollectionMapping()) { if (mapping.getAttributeName().equals("responsibilities")) { foundCount++; } } } assertFalse("We found multiple mappings for Employee responsibilities", foundCount == 2); } /** * Verifies that the read-only metadata is correctly processed. */ /* public void testReadOnlyClassSetting() { DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor descriptor = session.getDescriptor(ReadOnlyClass.class); assertFalse("ReadOnlyClass descriptor was not found in the PU [" + m_persistenceUnit + "]", descriptor == null); assertTrue("ReadOnlyClass descriptor is not set to read only.", descriptor.shouldBeReadOnly()); */ /** * Verifies that the change tracking metadata is correctly processed. * Employee has an AUTO setting, but has EAGER collections and transformation mapping * so should not be change tracked. */ public void testEmployeeChangeTrackingPolicy() { DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor descriptor = session.getDescriptor(Employee.class); assertFalse("Employee descriptor was not found in the PU [" + m_persistenceUnit + "]", descriptor == null); assertFalse("Employee descriptor has incorrect object change policy", descriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy()); } /** * Verifies that the change tracking metadata is correctly processed. */ public void testAddressChangeTrackingPolicy() { DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor descriptor = session.getDescriptor(Address.class); assertFalse("Address descriptor was not found in the PU [" + m_persistenceUnit + "]", descriptor == null); assertTrue("Address descriptor has incorrect object change policy", descriptor.getObjectChangePolicyInternal().isDeferredChangeDetectionPolicy()); } /** * Verifies that the change tracking metadata is correctly processed. */ public void testPhoneNumberChangeTrackingPolicy() { if (!isWeavingEnabled()) { return; } DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor descriptor = session.getDescriptor(PhoneNumber.class); assertFalse("PhoneNumber descriptor was not found in the PU [" + m_persistenceUnit + "]", descriptor == null); assertTrue("PhoneNumber descriptor has incorrect object change policy", descriptor.getObjectChangePolicy().isAttributeChangeTrackingPolicy()); } /** * Verifies that the change tracking metadata is correctly processed. */ public void testProjectChangeTrackingPolicy() { if (!isWeavingEnabled()) { return; } DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor descriptor = session.getDescriptor(Project.class); assertFalse("Project descriptor was not found in the PU [" + m_persistenceUnit + "]", descriptor == null); assertTrue("Project descriptor has incorrect object change policy", descriptor.getObjectChangePolicy().isObjectChangeTrackingPolicy()); } /** * Verifies that the join-fetch setting was read correctly from XML. */ public void testJoinFetchSetting() { DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor descriptor = session.getDescriptor(Employee.class); if (descriptor == null) { fail("Employee descriptor was not found in the PU [" + m_persistenceUnit + "]"); } else if (((ForeignReferenceMapping)descriptor.getMappingForAttributeName("address")).getJoinFetch() != ForeignReferenceMapping.OUTER_JOIN) { fail("join-fetch setting from XML was not read correctly for Employee's address."); } } /** * Verifies that the optimistic-locking settings were read correctly from XML. */ public void testEmployeeOptimisticLockingSettings() { DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor descriptor = session.getDescriptor(Employee.class); if (descriptor == null) { fail("Employee descriptor was not found in the PU [" + m_persistenceUnit + "]"); } else { assertTrue("Incorrect optimistic locking policy set on the Employee descriptor.", descriptor.usesVersionLocking()); assertTrue("Incorrect cascade option set on the optimistic locking poluicy.", descriptor.getOptimisticLockingPolicy().isCascaded()); } } /** * Verifies that settings from the Employee cache annotation have been set. * Also verifies that that employee customizer sets the disable cache hits * back to false. It is true in XML. */ public void testEmployeeCacheSettings() { DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor descriptor = session.getDescriptor(Employee.class); if (descriptor == null) { fail("A descriptor for the Employee alias was not found in the PU [" + m_persistenceUnit + "]"); } else { assertTrue("Incorrect cache type() setting.", descriptor.getIdentityMapClass().equals(ClassConstants.SoftCacheWeakIdentityMap_Class)); assertTrue("Incorrect cache size() setting.", descriptor.getIdentityMapSize() == 730); assertFalse("Incorrect cache isolated() setting.", descriptor.isIsolated()); assertFalse("Incorrect cache alwaysRefresh() setting.", descriptor.shouldAlwaysRefreshCache()); assertFalse("Incorrect disable hits setting.", descriptor.shouldDisableCacheHits()); CacheInvalidationPolicy policy = descriptor.getCacheInvalidationPolicy(); assertTrue("Incorrect cache expiry() policy setting.", policy instanceof TimeToLiveCacheInvalidationPolicy); assertTrue("Incorrect cache expiry() setting.", ((TimeToLiveCacheInvalidationPolicy) policy).getTimeToLive() == 1000); assertTrue("Incorrect cache coordinationType() settting.", descriptor.getCacheSynchronizationType() == ClassDescriptor.INVALIDATE_CHANGED_OBJECTS); } } /** * Verifies that the optimistic-locking settings were read correctly from XML. */ public void testProjectOptimisticLockingSettings() { DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor descriptor = session.getDescriptor(Project.class); if (descriptor == null) { fail("Project descriptor was not found in the PU [" + m_persistenceUnit + "]"); } else { OptimisticLockingPolicy policy = descriptor.getOptimisticLockingPolicy(); if (policy instanceof SelectedFieldsLockingPolicy) { List<DatabaseField> lockFields = ((SelectedFieldsLockingPolicy) policy).getLockFields(); if (lockFields.isEmpty() || lockFields.size() > 1) { fail("Invalid amount of lock fields were set on Project's selected fields locking policy."); } else { DatabaseField lockField = lockFields.get(0); assertTrue("Incorrect lock field was set on Project's selected fields locking policy.", lockField.getName().equals("VERSION")); } } else { fail("A SelectedFieldsLockingPolicy was not set on the Project descriptor."); } } } public void testCreateEmployee() { EntityManager em = createEntityManager(); beginTransaction(em); try { Employee employee = ModelExamples.employeeExample1(); ArrayList projects = new ArrayList(); projects.add(ModelExamples.projectExample1()); projects.add(ModelExamples.projectExample2()); employee.setProjects(projects); em.persist(employee); employeeId = employee.getId(); commitTransaction(em); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } } /** * Tests: * - BasicMap mapping with a TypeConverter on the map value and an * ObjectTypeConverter on the map key. * - Basic with a converter * - Basic with a custom converter */ public void testExtendedEmployee() { EntityManager em = createEntityManager(); beginTransaction(em); try { Address address = new Address(); address.setCity("Nepean"); address.setCountry("Canada"); address.setPostalCode("K2J 6T3"); // One it goes through the custom converter this should be // set to Ontario. address.setProvince("oNtArIo"); address.setStreet("321 Crestway"); Employee employee = new Employee(); employee.setGivenName("Boy"); employee.setFamilyName("Pelletier"); employee.setMale(); employee.addVisa(visa); employee.addAmex(amex); employee.addDinersClub(diners); employee.addMastercard(mastercard); employee.addRoyalBankCreditLine(rbc); employee.addScotiabankCreditLine(scotia); employee.addTorontoDominionCreditLine(td); employee.addCanadianImperialCreditLine(cibc); employee.setAddress(address); employee.setSalary(20000); employee.setPeriod(new EmploymentPeriod()); employee.getPeriod().setStartDate(new Date(System.currentTimeMillis()-1000000)); employee.getPeriod().setEndDate(new Date(System.currentTimeMillis()+1000000)); employee.addResponsibility("A very important responsibility"); em.persist(employee); extendedEmployeeId = employee.getId(); commitTransaction(em); clearCache(); em.clear(); // Re-read the employee and verify the data. Employee emp = em.find(Employee.class, extendedEmployeeId); assertNotNull("The employee was not found", emp); assertTrue("The address province value was not converted", emp.getAddress().getProvince().equals("Ontario")); assertTrue("Gender was not persisted correctly.", emp.isMale()); assertTrue("Visa card did not persist correctly.", emp.hasVisa(visa)); assertTrue("Amex card did not persist correctly.", emp.hasAmex(amex)); assertTrue("Diners Club card did not persist correctly.", emp.hasDinersClub(diners)); assertTrue("Mastercard card did not persist correctly.", emp.hasMastercard(mastercard)); assertTrue("RBC credit line did not persist correctly.", emp.hasRoyalBankCreditLine(rbc)); assertTrue("Scotia credit line did not persist correctly.", emp.hasScotiabankCreditLine(scotia)); assertTrue("TD credit line did not persist correctly.", emp.hasTorontoDominionCreditLine(td)); assertTrue("CIBC credit line did not persist correctly.", emp.hasCanadianImperialCreditLine(cibc)); boolean found = false; for (String responsibility : emp.getResponsibilities()) { if (responsibility.equals("A very important responsibility")) { found = true; break; } } assertTrue("The new responsibility was not added.", found); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } closeEntityManager(em); } /** * Tests an ObjectTypeConverter on a direct to field mapping. */ public void testGiveExtendedEmployeeASexChange() { EntityManager em = createEntityManager(); beginTransaction(em); try { Employee maleEmp = em.find(Employee.class, extendedEmployeeId); maleEmp.setFemale(); maleEmp.setGivenName("Girl"); commitTransaction(em); // Clear cache and clear the entity manager clearCache(); em.clear(); Employee girlEmp = em.find(Employee.class, extendedEmployeeId); assertTrue("The extended employee's change didn't occur.", girlEmp.isFemale()); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } closeEntityManager(em); } public void testDeleteEmployee() { EntityManager em = createEntityManager(); beginTransaction(em); try { em.remove(em.find(Employee.class, employeeId)); commitTransaction(em); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } assertTrue("Error deleting Employee", em.find(Employee.class, employeeId) == null); } public void testNamedNativeQueryOnAddress() { EntityManager em = createEntityManager(); beginTransaction(em); try { Address address1 = ModelExamples.addressExample1(); em.persist(address1); Address address2 = ModelExamples.addressExample2(); em.persist(address2); commitTransaction(em); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } Query query = em.createNamedQuery("findAllXMLAddresses"); List addresses = query.getResultList(); assertTrue("Error executing named native query 'findAllXMLAddresses'", addresses != null); } public void testNamedQueryOnEmployee() { Query query = createEntityManager().createNamedQuery("findAllXMLEmployeesByFirstName"); query.setParameter("firstname", "Brady"); Employee employee = (Employee) query.getSingleResult(); assertTrue("Error executing named query 'findAllXMLEmployeesByFirstName'", employee != null); } public void testReadEmployee() { Employee employee = createEntityManager().find(Employee.class, employeeId); assertTrue("Error reading Employee", employee.getId() == employeeId.intValue()); } public void testUpdateEmployee() { EntityManager em = createEntityManager(); beginTransaction(em); int version = 0; try { Employee employee = em.find(Employee.class, employeeId); version = employee.getVersion(); employee.setSalary(50000); em.merge(employee); commitTransaction(em); // Clear cache and clear the entity manager clearCache(); em.clear(); Employee emp = em.find(Employee.class, employeeId); assertTrue("Error updating Employee", emp.getSalary() == 50000); assertTrue("Version field not updated", emp.getVersion() == version + 1); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } closeEntityManager(em); } public void testRefreshNotManagedEmployee() { EntityManager em = createEntityManager(); beginTransaction(em); try { Employee emp = new Employee(); emp.setGivenName("NotManaged"); em.refresh(emp); fail("entityManager.refresh(notManagedObject) didn't throw exception"); } catch (IllegalArgumentException illegalArgumentException) { // expected behavior } catch (RuntimeException e ) { throw e; } finally { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); } } public void testRefreshRemovedEmployee() { // find an existing or create a new Employee String firstName = "testRefreshRemovedEmployee"; Employee emp; EntityManager em = createEntityManager(); List result = em.createQuery("SELECT OBJECT(e) FROM XMLEmployee e WHERE e.firstName = '"+firstName+"'").getResultList(); if(!result.isEmpty()) { emp = (Employee)result.get(0); } else { emp = new Employee(); emp.setGivenName(firstName); // persist the Employee beginTransaction(em); try { em.persist(emp); commitTransaction(em); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } } beginTransaction(em); try{ emp = em.find(Employee.class, emp.getId()); // Currently composite persistence unit doesn't support DeleteAll if there is a ManyToMany or DirectCollection with target in another session. // That situation causes attempt to join between two data bases, which is not possible. // The following JPQL // em.createQuery("DELETE FROM XMLEmployee e WHERE e.firstName = '"+firstName+"'").executeUpdate(); // generates: // DELETE FROM XML_BR3_PROJ_EMP WHERE EXISTS // (SELECT t0.EMP_ID FROM XML_BR2_EMPLOYEE t0, XML_BR2_SALARY t1 // WHERE ((t0.F_NAME = ?) AND (t1.E_ID = t0.EMP_ID)) AND t0.EMP_ID = XML_BR3_PROJ_EMP.EMP_ID) // In the sql above tables prefixed with XML_BR2_ and XML_BR3_ are in different data bases. List<Employee> employeesToBeDeleted = em.createQuery("SELECT e FROM XMLEmployee e WHERE e.firstName = '"+firstName+"'").getResultList(); for(Employee empToBeDeleted : employeesToBeDeleted) { int id = empToBeDeleted.getId(); // Note that for native query the user need to specify targetPU using COMPOSITE_MEMBER query hint. em.createNativeQuery("DELETE FROM XML_MBR2_SALARY WHERE E_ID = "+id).setHint(QueryHints.COMPOSITE_UNIT_MEMBER, getComponentMemberPuName(2)).executeUpdate(); em.createNativeQuery("DELETE FROM XML_MBR2_EMPLOYEE WHERE EMP_ID = "+id).setHint(QueryHints.COMPOSITE_UNIT_MEMBER, getComponentMemberPuName(2)).executeUpdate(); } // refresh the Employee - should fail with EntityNotFoundException em.refresh(emp); fail("entityManager.refresh(removedObject) didn't throw exception"); } catch (EntityNotFoundException entityNotFoundException) { // expected behavior } finally { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); } } public void testContainsRemovedEmployee() { // find an existing or create a new Employee String firstName = "testContainsRemovedEmployee"; Employee emp; EntityManager em = createEntityManager(); List result = em.createQuery("SELECT OBJECT(e) FROM XMLEmployee e WHERE e.firstName = '"+firstName+"'").getResultList(); if(!result.isEmpty()) { emp = (Employee)result.get(0); } else { emp = new Employee(); emp.setGivenName(firstName); // persist the Employee beginTransaction(em); try{ em.persist(emp); commitTransaction(em); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } } boolean containsRemoved = true; beginTransaction(em); try{ emp = em.find(Employee.class, emp.getId()); em.remove(emp); containsRemoved = em.contains(emp); commitTransaction(em); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } assertFalse("entityManager.contains(removedObject)==true ", containsRemoved); } public void testSubString() { // find an existing or create a new Employee String firstName = "testSubString"; Employee emp; EntityManager em = createEntityManager(); List result = em.createQuery("SELECT OBJECT(e) FROM XMLEmployee e WHERE e.firstName = '"+firstName+"'").getResultList(); if(!result.isEmpty()) { emp = (Employee)result.get(0); } else { emp = new Employee(); emp.setGivenName(firstName); // persist the Employee beginTransaction(em); try{ em.persist(emp); commitTransaction(em); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } } int firstIndex = 1; int lastIndex = firstName.length(); List employees = em.createQuery("SELECT object(e) FROM XMLEmployee e where e.firstName = substring(:p1, :p2, :p3)"). setParameter("p1", firstName). setParameter("p2", new Integer(firstIndex)). setParameter("p3", new Integer(lastIndex)). getResultList(); // clean up beginTransaction(em); try{ em.createQuery("DELETE FROM XML_BR2_Employee e WHERE e.firstName = '"+firstName+"'").executeUpdate(); commitTransaction(em); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); throw e; } assertFalse("employees.isEmpty()==true ", employees.isEmpty()); } /** * Tests a named-stored-procedure-query setting */ public void testNamedStoredProcedureQuery() { if (!supportsStoredProcedures()) { return; } EntityManager em = createEntityManager(); beginTransaction(em); try { Address address1 = new Address(); address1.setCity("Ottawa"); address1.setPostalCode("K1G6P3"); address1.setProvince("ON"); address1.setStreet("123 Street"); address1.setCountry("Canada"); em.persist(address1); commitTransaction(em); // 260263 and 302316: clear the cache or we will end up with a false positive when comparing the entity to itself later em.clear(); Query aQuery = em.createNamedQuery("SProcXMLAddress").setParameter("ADDRESS_ID", address1.getId()); Address address2 = (Address) aQuery.getSingleResult(); assertNotNull("Address returned from stored procedure is null", address2); assertFalse("Address returned is the same cached instance that was persisted - the cache must be disabled for this test", address1 == address2); // new // Integer address handled differently than int assertTrue("Address not found using stored procedure", address1.getId().intValue() == address2.getId().intValue()); assertTrue("Address.street data returned doesn't match persisted address.street", address1.getStreet().equals(address2.getStreet())); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); // Re-throw exception to ensure stacktrace appears in test result. throw e; } closeEntityManager(em); } /** * Tests a named-stored-procedure-query setting */ public void testNamedStoredProcedureQueryInOut() { if (!supportsStoredProcedures()) { return; } EntityManager em = createEntityManager(); beginTransaction(em); try { Address address1 = new Address(); address1.setCity("Ottawa"); address1.setPostalCode("K1G6P3"); address1.setProvince("ON"); address1.setStreet("123 Street"); address1.setCountry("Canada"); em.persist(address1); commitTransaction(em); // 260263 and 302316: clear the cache or we will end up with a false positive when comparing the entity to itself later em.clear(); Query aQuery = em.createNamedQuery("SProcXMLInOut").setParameter("ADDRESS_ID", address1.getId()); Address address2 = (Address) aQuery.getSingleResult(); assertNotNull("Address returned from stored procedure is null", address2); assertFalse("Address returned is the same cached instance that was persisted - the cache must be disabled for this test", address1 == address2); // new // Integer address handled differently than int assertTrue("Address not found using stored procedure", address1.getId().intValue() == address2.getId().intValue()); assertTrue("Address.street data returned doesn't match persisted address.street", address1.getStreet().equals(address2.getStreet())); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); // Re-throw exception to ensure stacktrace appears in test result. throw e; } closeEntityManager(em); } public void testMethodBasedTransformationMapping() { internalTestTransformationMapping("normalHours"); } public void testClassBasedTransformationMapping() { internalTestTransformationMapping("overtimeHours"); } protected void internalTestTransformationMapping(String attributeName) { // setup: create an Employee, insert into db int startHour = 8, startMin = 30, startSec = 15; int endHour = 17, endMin = 15, endSec = 45; String firstName = attributeName; Employee employee = new Employee(); employee.setGivenName(firstName); if(attributeName.equals("normalHours")) { employee.setStartTime(Helper.timeFromHourMinuteSecond(startHour, startMin, startSec)); employee.setEndTime(Helper.timeFromHourMinuteSecond(endHour, endMin, endSec)); } else if(attributeName.equals("overtimeHours")) { employee.setStartOvertime(Helper.timeFromHourMinuteSecond(startHour, startMin, startSec)); employee.setEndOvertime(Helper.timeFromHourMinuteSecond(endHour, endMin, endSec)); } else { throw new RuntimeException("Unknown attributeName"); } EntityManager em = createEntityManager(); beginTransaction(em); try { em.persist(employee); commitTransaction(em); } finally { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); } int id = employee.getId(); // test // clear cache this.clearCache(); // read the employee from the db em = createEntityManager(); employee = em.find(Employee.class,id); // verify Calendar calendarStart = Calendar.getInstance(); Calendar calendarEnd = Calendar.getInstance(); if(attributeName.equals("normalHours")) { calendarStart.setTime(employee.getStartTime()); calendarEnd.setTime(employee.getEndTime()); } else if(attributeName.equals("overtimeHours")) { calendarStart.setTime(employee.getStartOvertime()); calendarEnd.setTime(employee.getEndOvertime()); } String errorMsg = ""; if(calendarStart.get(Calendar.HOUR_OF_DAY) != startHour || calendarStart.get(Calendar.MINUTE) != startMin || calendarStart.get(Calendar.SECOND) != startSec) { if(attributeName.equals("normalHours")) { errorMsg = "startTime = " + employee.getStartTime().toString() + " is wrong"; } else if(attributeName.equals("overtimeHours")) { errorMsg = "startOvertime = " + employee.getStartOvertime().toString() + " is wrong"; } } if(calendarEnd.get(Calendar.HOUR_OF_DAY) != endHour || calendarEnd.get(Calendar.MINUTE) != endMin || calendarEnd.get(Calendar.SECOND) != endSec) { if(errorMsg.length() > 0) { errorMsg = errorMsg + "; "; } if(attributeName.equals("normalHours")) { errorMsg = "endTime = " + employee.getEndTime().toString() + " is wrong"; } else if(attributeName.equals("overtimeHours")) { errorMsg = "endOvertime = " + employee.getEndOvertime().toString() + " is wrong"; } } // clean up beginTransaction(em); try { em.remove(employee); commitTransaction(em); } finally { if (isTransactionActive(em)){ rollbackTransaction(em); } closeEntityManager(em); } if(errorMsg.length() > 0) { fail(errorMsg); } } public void testClassInstanceConverter(){ EntityManager em = createEntityManager(); beginTransaction(em); Address add = new Address(); add.setCity("St. Louis"); add.setType(new Bungalow()); em.persist(add); commitTransaction(em); int assignedSequenceNumber = add.getId(); em.clear(); getDatabaseSession().getIdentityMapAccessor().initializeAllIdentityMaps(); add = em.find(Address.class, assignedSequenceNumber); assertTrue("Did not correctly persist a mapping using a class-instance converter", (add.getType() instanceof Bungalow)); beginTransaction(em); em.remove(add); commitTransaction(em); } /** * Tests Property and Properties annotations */ public void testProperty() { EntityManager em = createEntityManager(); DatabaseSessionImpl session = getDatabaseSession(); ClassDescriptor descriptor = session.getDescriptorForAlias("XMLEmployee"); ClassDescriptor aggregateDescriptor = session.getDescriptor(EmploymentPeriod.class); em.close(); String errorMsg = ""; if (descriptor == null) { errorMsg += " Descriptor for XMLEmployee alias was not found;"; } if (aggregateDescriptor == null) { errorMsg += " Descriptor for EmploymentPeriod.class was not found;"; } if(errorMsg.length() > 0) { fail(errorMsg); } // verify properties set on Employee instance errorMsg += verifyPropertyValue(descriptor, "entityName", String.class, "XMLEmployee"); errorMsg += verifyPropertyValue(descriptor, "entityIntegerProperty", Integer.class, new Integer(1)); errorMsg += verifyPropertyValue(descriptor, "ToBeOverriddenByXml", Boolean.class, Boolean.TRUE); errorMsg += verifyPropertyValue(descriptor, "ToBeProcessed", Boolean.class, Boolean.TRUE); // each attribute of Employee was assigned a property attributeName with the value attribute name. for(DatabaseMapping mapping : descriptor.getMappings()) { errorMsg += verifyPropertyValue(mapping, "attributeName", String.class, mapping.getAttributeName()); } // attribute m_lastName has many properties of different types DatabaseMapping mapping = descriptor.getMappingForAttributeName("lastName"); errorMsg += verifyPropertyValue(mapping, "BooleanProperty", Boolean.class, Boolean.TRUE); errorMsg += verifyPropertyValue(mapping, "ByteProperty", Byte.class, new Byte((byte)1)); errorMsg += verifyPropertyValue(mapping, "CharacterProperty", Character.class, new Character('A')); errorMsg += verifyPropertyValue(mapping, "DoubleProperty", Double.class, new Double(1)); errorMsg += verifyPropertyValue(mapping, "FloatProperty", Float.class, new Float(1)); errorMsg += verifyPropertyValue(mapping, "IntegerProperty", Integer.class, new Integer(1)); errorMsg += verifyPropertyValue(mapping, "LongProperty", Long.class, new Long(1)); errorMsg += verifyPropertyValue(mapping, "ShortProperty", Short.class, new Short((short)1)); errorMsg += verifyPropertyValue(mapping, "BigDecimalProperty", java.math.BigDecimal.class, java.math.BigDecimal.ONE); errorMsg += verifyPropertyValue(mapping, "BigIntegerProperty", java.math.BigInteger.class, java.math.BigInteger.ONE); errorMsg += verifyPropertyValue(mapping, "TimeProperty", java.sql.Time.class, Helper.timeFromString("13:59:59")); errorMsg += verifyPropertyValue(mapping, "TimeStampProperty", java.sql.Timestamp.class, Helper.timestampFromString("2008-04-10 13:59:59")); errorMsg += verifyPropertyValue(mapping, "DateProperty", java.sql.Date.class, Helper.dateFromString("2008-04-10")); errorMsg += verifyPropertyValue(mapping, "ToBeIgnored", null, null); // verify property set on EmploymentPeriod embeddable errorMsg += verifyPropertyValue(aggregateDescriptor, "embeddableClassName", String.class, "EmploymentPeriod"); errorMsg += verifyPropertyValue(aggregateDescriptor, "ToBeOverriddenByXml", Boolean.class, Boolean.TRUE); errorMsg += verifyPropertyValue(aggregateDescriptor, "ToBeProcessed", Boolean.class, Boolean.TRUE); if(errorMsg.length() > 0) { fail(errorMsg); } } protected String verifyPropertyValue(ClassDescriptor descriptor, String propertyName, Class expectedPropertyValueType, Object expectedPropertyValue) { return verifyPropertyValue(propertyName, descriptor.getProperty(propertyName), expectedPropertyValueType, expectedPropertyValue, Helper.getShortClassName(descriptor.getJavaClass()) + " descriptor"); } protected String verifyPropertyValue(DatabaseMapping mapping, String propertyName, Class expectedPropertyValueType, Object expectedPropertyValue) { return verifyPropertyValue(propertyName, mapping.getProperty(propertyName), expectedPropertyValueType, expectedPropertyValue, mapping.getAttributeName() + " attribute"); } protected String verifyPropertyValue(String propertyName, Object propertyValue, Class expectedPropertyValueType, Object expectedPropertyValue, String masterName) { String errorMsg = ""; String errorPrefix = " property " + propertyName + " for " + masterName; if(expectedPropertyValueType == null) { if(propertyValue != null) { errorMsg = errorPrefix + " value is " + propertyValue.toString() + " , was expected to be null."; } return errorMsg; } if(propertyValue == null) { errorMsg = errorPrefix + " is missing;"; } else if(!expectedPropertyValueType.isInstance(propertyValue)) { errorMsg = errorPrefix + " is instance of " + propertyValue.getClass().getName() + ", " + expectedPropertyValueType.getName() + " was expected;"; } else { if(propertyValue.getClass().isArray()) { if(Array.getLength(propertyValue) != Array.getLength(expectedPropertyValue)) { errorMsg = errorPrefix + " has array value of size " + Array.getLength(propertyValue) + ", " + Array.getLength(expectedPropertyValue) + " was expected;"; } else { for(int i=0; i < Array.getLength(propertyValue); i++) { if(!Array.get(propertyValue, i).equals(Array.get(expectedPropertyValue, i))) { errorMsg = errorPrefix + " has array with "+i+"th element value " + Array.get(propertyValue, i).toString() + ", " + Array.get(expectedPropertyValue, i).toString() + " was expected;"; } } } } else if (!propertyValue.equals(expectedPropertyValue)) { errorMsg = errorPrefix + " has value " + propertyValue.toString() + ", " + expectedPropertyValue.toString() + " was expected;"; } } return errorMsg; } public void testUnidirectionalPersist() { String lastName = "testUnidirectionalPersist"; // persist employees List<Employee> employeesPersisted = persistEmployeesWithUnidirectionalMappings(lastName); // clear cache clearCache(); // read the persisted employees back EntityManager em = createEntityManager(); List<Employee> employeesRead = em.createQuery("SELECT OBJECT(e) FROM XMLEmployee e WHERE e.lastName = '"+lastName+"'").getResultList(); // while em is open, cache ServerSession that will be used later for verification DatabaseSessionImpl session = getDatabaseSession(); closeEntityManager(em); // verify number persisted and read is the same if(employeesPersisted.size() != employeesRead.size()) { //clean-up deleteEmployeesWithUnidirectionalMappings(lastName); fail("Persisted " + employeesPersisted.size() + " employees, but read back " + employeesRead.size()); } // verify that the persisted and read objects are equal String errorMsg = ""; for(int i=0; i<employeesPersisted.size(); i++) { for(int j=0; j<employeesRead.size(); j++) { if(employeesPersisted.get(i).getFirstName().equals(employeesRead.get(j).getFirstName())) { if(!session.compareObjects(employeesPersisted.get(i), employeesRead.get(j))) { errorMsg += "Employee " + employeesPersisted.get(i).getFirstName() +" was not persisted correctly."; } } } } // clean-up deleteEmployeesWithUnidirectionalMappings(lastName); // non-empty error message means the test has failed if(errorMsg.length() > 0) { fail(errorMsg); } } public void testUnidirectionalUpdate() { String lastName = "testUnidirectionalUpdate"; // em used for both persist and update EntityManager em = createEntityManager(); // persist employees List<Employee> employeesPersisted = persistEmployeesWithUnidirectionalMappings(lastName, em); // update persisted employees: beginTransaction(em); try { // add a new dealer to the first employee employeesPersisted.get(0).addDealer(new Dealer("New", lastName)); // remove a dealer from the second employee employeesPersisted.get(1).getDealers().remove(1); // move a dealer from the first to the second employee employeesPersisted.get(1).addDealer(employeesPersisted.get(0).getDealers().remove(0)); commitTransaction(em); } finally { if(this.isTransactionActive(em)) { rollbackTransaction(em); } closeEntityManager(em); } // clear cache clearCache(); em = createEntityManager(); // read the updated employees back List<Employee> employeesRead = em.createQuery("SELECT OBJECT(e) FROM XMLEmployee e WHERE e.lastName = '"+lastName+"'").getResultList(); // while em is open, cache ServerSession that will be used later for verification DatabaseSessionImpl session = getDatabaseSession(); // verify number persisted and read is the same if(employeesPersisted.size() != employeesRead.size()) { // clean-up deleteEmployeesWithUnidirectionalMappings(lastName); fail("Updated " + employeesPersisted.size() + " employees, but read back " + employeesRead.size()); } // verify that the persisted and read objects are equal beginTransaction(em); String errorMsg = ""; try{ for(int i=0; i<employeesPersisted.size(); i++) { for(int j=0; j<employeesRead.size(); j++) { Employee emp1 = em.find(Employee.class, employeesPersisted.get(i).getId()); Employee emp2 = em.find(Employee.class, employeesRead.get(j).getId()); if(emp1.getFirstName().equals(emp2.getFirstName())) { if(!session.compareObjects(emp1, emp2)) { errorMsg += "Employee " + emp1.getFirstName() +" was not updated correctly."; } } } } } finally { if(this.isTransactionActive(em)) { rollbackTransaction(em); } closeEntityManager(em); } // clean-up deleteEmployeesWithUnidirectionalMappings(lastName); // non-empty error message means the test has failed if(errorMsg.length() > 0) { fail(errorMsg); } } public void testUnidirectionalFetchJoin() { String lastName = "testUnidirectionalFetchJoin"; // persist employees persistEmployeesWithUnidirectionalMappings(lastName); // clear cache clearCache(); EntityManager em = createEntityManager(); // read the persisted employees back - without fetch join List<Employee> employeesRead = em.createQuery("SELECT OBJECT(e) FROM XMLEmployee e WHERE e.lastName = '"+lastName+"'").getResultList(); closeEntityManager(em); // clear cache clearCache(); // read the persisted employees back - with fetch join. em = createEntityManager(); List<Employee> employeesReadWithFetchJoin = em.createQuery("SELECT e FROM XMLEmployee e JOIN FETCH e.dealers WHERE e.lastName = '"+lastName+"'").getResultList(); // while em is open, cache ServerSession that will be used later for verification DatabaseSessionImpl session = getDatabaseSession(); closeEntityManager(em); // verify that the persisted and read employees are the same. // The comparison cascades to all references and requires the same state of indirection: // it fails in case an object has triggered indirection for particular attribute and compared object's indirection for this attribute is not triggered. // The expected result of join fetch query is Employee.dealers being triggered - so need to trigger it on the control collection (getDealers.size() does that); // also the expected result should have an object for each row returned - therefore number of inclusions of each Employee equals its dealers.size() List<Employee> employeesControl = new ArrayList<Employee>(); for(int i=0; i<employeesRead.size(); i++) { int nDialers = employeesRead.get(i).getDealers().size(); for(int j=0; j<nDialers; j++) { employeesControl.add(employeesRead.get(i)); } } String errorMsg = JoinedAttributeTestHelper.compareCollections(employeesControl, employeesReadWithFetchJoin, session.getClassDescriptor(Employee.class), session); // clean-up deleteEmployeesWithUnidirectionalMappings(lastName); // non-empty error message means the test has failed if(errorMsg.length() > 0) { fail(errorMsg); } } public void testUnidirectionalTargetLocking_AddRemoveTarget() { String lastName = "testUnidirectionalTargetLocking_ART"; EntityManager em = createEntityManager(); // persist employees List<Employee> employeesPersisted = persistEmployeesWithUnidirectionalMappings(lastName, em); // remove a dealer from the second employee: Dealer dealer; beginTransaction(em); try { Employee emp1 = em.find(Employee.class, employeesPersisted.get(1).getId()); dealer = emp1.getDealers().remove(1); commitTransaction(em); } finally { if(this.isTransactionActive(em)) { rollbackTransaction(em); closeEntityManager(em); } } String errorMsg = ""; // verify the version both in the cache and in the db int version2 = getVersion(em, dealer); if(version2 != 2) { errorMsg += "In the cache the removed dealer's version is " + version2 + " (2 was expected); "; } // add the dealer to the first employee: //version2 = getDealerVersionFromDB(em, dealer); beginTransaction(em); try { Dealer dealer2 = em.find(Dealer.class, dealer.getId()); em.refresh(dealer2); version2 = getVersion(em, dealer2); } finally { if(this.isTransactionActive(em)) { rollbackTransaction(em); } } if(version2 != 2) { errorMsg += "In the db the removed dealer's version is " + version2 + " (2 was expected); "; } beginTransaction(em); Dealer dealer3; try { Employee emp2 = em.find(Employee.class, employeesPersisted.get(1).getId()); dealer3 = em.find(Dealer.class, dealer.getId()); emp2.getDealers().add(dealer3); commitTransaction(em); } finally { if(this.isTransactionActive(em)) { rollbackTransaction(em); closeEntityManager(em); } } // verify the version both in the cache and in the db int version3 = getVersion(em, dealer3); if(version3 != 3) { errorMsg += "In the cache the added dealer's version is " + version3 + " (3 was expected); "; } beginTransaction(em); try { Dealer dealer4 = em.find(Dealer.class, dealer3.getId()); em.refresh(dealer4); version3 = getVersion(em, dealer4); } finally { if(this.isTransactionActive(em)) { rollbackTransaction(em); } } if(version3 != 3) { errorMsg += "In the db the added dealer's version is " + version3 + " (3 was expected)"; } closeEntityManager(em); // clean-up deleteEmployeesWithUnidirectionalMappings(lastName); // non-empty error message means the test has failed if(errorMsg.length() > 0) { fail(errorMsg); } } public void testUnidirectionalTargetLocking_DeleteSource() { String lastName = "testUnidirectionalTargetLocking_DS"; // persist employees (there should be two of them) List<Employee> persistedEmployees = persistEmployeesWithUnidirectionalMappings(lastName); // cache their dealers' ids ArrayList<Integer> dealersIds = new ArrayList<Integer>(); for(int i=0; i<persistedEmployees.size(); i++) { Employee emp = persistedEmployees.get(i); for(int j=0; j<emp.getDealers().size(); j++) { dealersIds.add(emp.getDealers().get(j).getId()); } } // clear cache clearCache(); EntityManager em = createEntityManager(); beginTransaction(em); // read the persisted employees List<Employee> readEmployees = em.createQuery("SELECT OBJECT(e) FROM XMLEmployee e WHERE e.lastName = '"+lastName+"'").getResultList(); // trigger indirection on the second employee's dealers readEmployees.get(1).getDealers().size(); // delete the Employees (there should be two of them). try { for(Employee emp: readEmployees) { em.remove(emp); } commitTransaction(em); } finally { if(this.isTransactionActive(em)) { rollbackTransaction(em); closeEntityManager(em); } } // find employees' dealers and verify their versions - all should be 2. beginTransaction(em); String errorMsg = ""; try{ for(int i=0; i<dealersIds.size(); i++) { Dealer dealer = em.find(Dealer.class, dealersIds.get(i)); // verify the version both in the cache and in the db int version2 = getVersion(em, dealer); if(version2 != 2) { errorMsg += "In the cache dealer "+dealer.getFirstName()+"'s version is " + version2 + " (2 was expected); "; } em.refresh(dealer); version2 = getVersion(em, dealer); if(version2 != 2) { errorMsg += "In the db dealer "+dealer.getFirstName()+"'s version is " + version2 + " (2 was expected); "; } } } finally { if(this.isTransactionActive(em)) { rollbackTransaction(em); } } closeEntityManager(em); // clean-up deleteEmployeesWithUnidirectionalMappings(lastName); // non-empty error message means the test has failed if(errorMsg.length() > 0) { fail(errorMsg); } } protected int getVersion(EntityManager em, Dealer dealer) { Vector pk = new Vector(1); pk.add(dealer.getId()); DatabaseSessionImpl session = getDatabaseSession(); return ((Integer)session.getDescriptor(Dealer.class).getOptimisticLockingPolicy().getWriteLockValue(dealer, pk, session)).intValue(); } protected List<Employee> createEmployeesWithUnidirectionalMappings(String lastName) { int n = 2; List<Employee> employees = new ArrayList<Employee>(n); for(int i=0; i<n; i++) { Employee emp = new Employee(); emp.setGivenName(Integer.toString(i+1)); emp.setFamilyName(lastName); employees.add(emp); for(int j=0; j<n; j++) { Dealer dealer = new Dealer(); dealer.setFirstName(emp.getFirstName() + "_" + Integer.toString(j+1)); dealer.setLastName(lastName); emp.addDealer(dealer); for(int k=0; k<n; k++) { Customer customer = new Customer(); customer.setFirstName(dealer.getFirstName() + "_" + Integer.toString(k+1)); customer.setLastName(lastName); dealer.addCustomer(customer); } } } return employees; } protected List<Employee> persistEmployeesWithUnidirectionalMappings(String lastName) { EntityManager em = createEntityManager(); try { return persistEmployeesWithUnidirectionalMappings(lastName, em); } finally { closeEntityManager(em); } } protected List<Employee> persistEmployeesWithUnidirectionalMappings(String lastName, EntityManager em) { List<Employee> employees = createEmployeesWithUnidirectionalMappings(lastName); beginTransaction(em); try { for(int i=0; i<employees.size(); i++) { em.persist(employees.get(i)); } commitTransaction(em); } finally { if(this.isTransactionActive(em)) { rollbackTransaction(em); } } return employees; } protected void deleteEmployeesWithUnidirectionalMappings(String lastName) { EntityManager em = createEntityManager(); beginTransaction(em); try { em.createQuery("DELETE FROM XMLCustomer c WHERE c.lastName = '"+lastName+"'").executeUpdate(); em.createQuery("DELETE FROM XMLDealer d WHERE d.lastName = '"+lastName+"'").executeUpdate(); Query q = em.createQuery("SELECT e FROM XMLEmployee e WHERE e.lastName = '"+lastName+"'"); for (Object oldData : q.getResultList()) { em.remove(oldData); } commitTransaction(em); } finally { if(this.isTransactionActive(em)) { rollbackTransaction(em); } closeEntityManager(em); clearCache(); } } public void testMustBeCompositeMember() { String errorMsg = ""; for(int i=1; i<=3; i++) { String puName = getComponentMemberPuName(i); try { EntityManager em = createEntityManager(puName); closeEntityManager(em); if (i == 1) { // "xml-composite-advanced-member_1" is not marked as mustBeCompositeMember - should work standalone, too. } else { errorMsg += "createEntityManager(" + puName +") succeeded - should have failed\n"; } } catch (IllegalStateException ex){ if (i == 1) { errorMsg += "createEntityManager(" + puName +") failed - should have succeeded\n"; } else { // expected exception } } catch (Exception exWrong) { errorMsg += "createEntityManager(" + puName +") threw wrong exception: " + exWrong +"\n"; } finally { closeEntityManagerFactory(puName); } } } /** * Verifies that attribute-types are correctly processed and used. */ /* public void testAttributeTypeSpecifications() { EntityManager em = createEntityManager(); try { beginTransaction(em); Loner loner = new Loner(); Name name = new Name(); name.firstName = "Joe"; name.lastName = "Schmo"; loner.setName(name); Confidant confidant = new Confidant(); loner.addConfidant(confidant); loner.addCharacteristic("Keeps to himself"); loner.addCharacteristic("Shy's away from conversation"); em.persist(loner); Object lonerId = loner.getId(); commitTransaction(em); clearCache(); em.clear(); Loner refreshedLoner = em.find(Loner.class, lonerId); assertTrue("Loner objects didn't match", getDatabaseSession().compareObjects(loner, refreshedLoner)); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } throw e; } finally { closeEntityManager(em); } }*/ /** * Verifies that attribute-types and name access are correctly processed * and used. */ /* public void testMockDynamicClassCRUD() { EntityManager em = createEntityManager(); try { beginTransaction(em); // Cost Shovel shovel = new Shovel(); shovel.setMy("cost", Double.valueOf(9.99)); // Sections ShovelSections shovelSections = new ShovelSections(); shovelSections.setMaterial("handle", MaterialType.Plastic); shovelSections.setMaterial("shaft", MaterialType.Wood); shovelSections.setMaterial("scoop", MaterialType.Plastic); shovel.setMy("sections", shovelSections); // Owner ShovelOwner shovelOwner = new ShovelOwner(); shovelOwner.set("name", "Mr. Shovel"); shovel.setMy("owner", shovelOwner); // Operators ShovelDigger shovelDigger1 = new ShovelDigger(); shovelDigger1.set("name", "Digging Plebe 1"); shovelDigger1.setX("shovel", shovel); ShovelDigger shovelDigger2 = new ShovelDigger(); shovelDigger2.set("name", "Digging Plebe 2"); shovelDigger2.setX("shovel", shovel); List<ShovelDigger> operators = new ArrayList<ShovelDigger>(); operators.add(shovelDigger1); operators.add(shovelDigger2); shovel.setMy("operators", operators); // Projects ShovelProject shovelProject = new ShovelProject(); shovelProject.set("description", "One lousy shovelling project"); List<Shovel> shovels = new ArrayList<Shovel>(); shovels.add(shovel); shovelProject.set("shovels", shovels); List<ShovelProject> projects = new ArrayList<ShovelProject>(); projects.add(shovelProject); shovel.setMy("projects", projects); em.persist(shovel); // Grab id's for ease of lookup. Object shovelId = shovel.getMy("id"); Object shovelOwnerId = shovelOwner.get("id"); Object shovelDigger1Id = shovelDigger1.get("id"); Object shovelDigger2Id = shovelDigger2.get("id"); Object shovelProjectId = shovelProject.get("id"); commitTransaction(em); clearCache(); em.clear(); Shovel refreshedShovel = em.find(Shovel.class, shovelId); assertTrue("Shovel didn't match after write/read", getDatabaseSession().compareObjects(shovel, refreshedShovel)); // Do an update beginTransaction(em); em.merge(refreshedShovel); refreshedShovel.setMy("cost", Double.valueOf(7.99)); commitTransaction(em); clearCache(); em.clear(); Shovel refreshedUpdatedShovel = em.find(Shovel.class, shovelId); assertTrue("Shovel didn't match after update", getDatabaseSession().compareObjects(refreshedShovel, refreshedUpdatedShovel)); // Now delete it beginTransaction(em); em.merge(refreshedUpdatedShovel); em.remove(refreshedUpdatedShovel); commitTransaction(em); // Check what's left assertNull("Shovel wasn't removed", em.find(Shovel.class, shovelId)); assertNull("Shovel owner wasn't removed", em.find(ShovelOwner.class, shovelOwnerId)); assertNull("Shovel digger 1 wasn't removed", em.find(ShovelDigger.class, shovelDigger1Id)); assertNull("Shovel digger 2 wasn't removed", em.find(ShovelDigger.class, shovelDigger2Id)); assertNotNull("Shovel project was removed", em.find(ShovelProject.class, shovelProjectId)); } catch (RuntimeException e) { if (isTransactionActive(em)){ rollbackTransaction(em); } throw e; } finally { closeEntityManager(em); } }*/ /** * Fix for bug 247078: eclipselink-orm.xml schema should allow lob and * enumerated on version and id mappings */ /* public void testEnumeratedPrimaryKeys(){ EntityManager em = createEntityManager(); try { beginTransaction(em); ViolationCode codeA = new ViolationCode(); codeA.setId(ViolationCodeId.A); codeA.setDescription("Violation A"); em.persist(codeA); ViolationCode codeB = new ViolationCode(); codeB.setId(ViolationCodeId.B); codeB.setDescription("Violation B"); em.persist(codeB); ViolationCode codeC = new ViolationCode(); codeC.setId(ViolationCodeId.C); codeC.setDescription("Violation C"); em.persist(codeC); ViolationCode codeD = new ViolationCode(); codeD.setId(ViolationCodeId.D); codeD.setDescription("Violation D"); em.persist(codeD); Violation violation = new Violation(); violation.setId(ViolationID.V1); violation.getViolationCodes().add(codeA); violation.getViolationCodes().add(codeC); violation.getViolationCodes().add(codeD); em.persist(violation); commitTransaction(em); // Force the read to hit the database and make sure the violation is read back. clearCache(); em.clear(); Violation refreshedViolation = em.find(Violation.class, violation.getId()); assertNotNull("Unable to read back the violation", refreshedViolation); assertTrue("Violation object did not match after refresh", getDatabaseSession().compareObjects(violation, refreshedViolation)); } catch (Exception e) { fail("An error occurred: " + e.getMessage()); } finally { closeEntityManager(em); } }*/ }