blob: 984f8ad48d164dc933332c43ae8b99f42cdc3979 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 1998, 2016 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
* 03/03/2010 - 2.1 Michael O'Brien
* - 302316: clear the object cache when testing stored procedure returns on SQLServer
* to avoid false positives visible only when debugging in DatabaseCall.buildOutputRow()
* - 260263: SQLServer 2005/2008 requires stored procedure creation select clause variable and column name matching
* 06/16/2010-2.2 Guy Pelletier
* - 247078: eclipselink-orm.xml schema should allow lob and enumerated on version and id mappings
* 09/03/2010-2.2 Guy Pelletier
* - 317286: DB column lenght not in sync between @Column and @JoinColumn
* 10/15/2010-2.2 Guy Pelletier
* - 322008: Improve usability of additional criteria applied to queries at the session/EM
* 10/27/2010-2.2 Guy Pelletier
* - 328114: @AttributeOverride does not work with nested embeddables having attributes of the same name
* 11/01/2010-2.2 Guy Pelletier
* - 322916: getParameter on Query throws NPE
* 15/08/2011-2.3.1 Guy Pelletier
* - 298494: JPQL exists subquery generates unnecessary table join
******************************************************************************/
package org.eclipse.persistence.testing.tests.jpa.advanced;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.beans.PropertyChangeListener;
import javax.persistence.CacheStoreMode;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.MapAttribute;
import javax.persistence.metamodel.Metamodel;
import javax.persistence.metamodel.SingularAttribute;
import javax.persistence.metamodel.Attribute.PersistentAttributeType;
import javax.persistence.metamodel.Bindable.BindableType;
import javax.persistence.metamodel.Type.PersistenceType;
import junit.framework.Test;
import junit.framework.TestSuite;
import org.eclipse.persistence.config.QueryHints;
import org.eclipse.persistence.descriptors.ClassDescriptor;
import org.eclipse.persistence.descriptors.DescriptorEvent;
import org.eclipse.persistence.descriptors.DescriptorEventAdapter;
import org.eclipse.persistence.descriptors.changetracking.ChangeTracker;
import org.eclipse.persistence.internal.descriptors.changetracking.AttributeChangeListener;
import org.eclipse.persistence.descriptors.invalidation.CacheInvalidationPolicy;
import org.eclipse.persistence.descriptors.invalidation.TimeToLiveCacheInvalidationPolicy;
import org.eclipse.persistence.indirection.IndirectContainer;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.internal.helper.ClassConstants;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.helper.DatabaseTable;
import org.eclipse.persistence.indirection.IndirectCollection;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.indirection.DatabaseValueHolder;
import org.eclipse.persistence.internal.indirection.QueryBasedValueHolder;
import org.eclipse.persistence.internal.jpa.EJBQueryImpl;
import org.eclipse.persistence.internal.jpa.EntityManagerFactoryDelegate;
import org.eclipse.persistence.internal.jpa.EntityManagerImpl;
import org.eclipse.persistence.internal.jpa.metamodel.MapAttributeImpl;
import org.eclipse.persistence.internal.jpa.metamodel.SingularAttributeImpl;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.jpa.JpaHelper;
import org.eclipse.persistence.mappings.DatabaseMapping;
import org.eclipse.persistence.mappings.DirectCollectionMapping;
import org.eclipse.persistence.mappings.ForeignReferenceMapping;
import org.eclipse.persistence.mappings.ManyToManyMapping;
import org.eclipse.persistence.mappings.OneToManyMapping;
import org.eclipse.persistence.mappings.OneToOneMapping;
import org.eclipse.persistence.mappings.UnidirectionalOneToManyMapping;
import org.eclipse.persistence.queries.DatabaseQuery;
import org.eclipse.persistence.queries.DoesExistQuery;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.sessions.server.ServerSession;
import org.eclipse.persistence.testing.framework.JoinedAttributeTestHelper;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCase;
import org.eclipse.persistence.testing.framework.junit.JUnitTestCaseHelper;
import org.eclipse.persistence.testing.models.jpa.advanced.Bill;
import org.eclipse.persistence.testing.models.jpa.advanced.BillLine;
import org.eclipse.persistence.testing.models.jpa.advanced.BillLineItem;
import org.eclipse.persistence.testing.models.jpa.advanced.BillAction;
import org.eclipse.persistence.testing.models.jpa.advanced.Address;
import org.eclipse.persistence.testing.models.jpa.advanced.AdvancedTableCreator;
import org.eclipse.persistence.testing.models.jpa.advanced.Bag;
import org.eclipse.persistence.testing.models.jpa.advanced.Buyer;
import org.eclipse.persistence.testing.models.jpa.advanced.Cost;
import org.eclipse.persistence.testing.models.jpa.advanced.Customer;
import org.eclipse.persistence.testing.models.jpa.advanced.Dealer;
import org.eclipse.persistence.testing.models.jpa.advanced.Department;
import org.eclipse.persistence.testing.models.jpa.advanced.Employee;
import org.eclipse.persistence.testing.models.jpa.advanced.EmployeePopulator;
import org.eclipse.persistence.testing.models.jpa.advanced.EmploymentPeriod;
import org.eclipse.persistence.testing.models.jpa.advanced.Equipment;
import org.eclipse.persistence.testing.models.jpa.advanced.EquipmentCode;
import org.eclipse.persistence.testing.models.jpa.advanced.GoldBuyer;
import org.eclipse.persistence.testing.models.jpa.advanced.Jigsaw;
import org.eclipse.persistence.testing.models.jpa.advanced.JigsawPiece;
import org.eclipse.persistence.testing.models.jpa.advanced.LargeProject;
import org.eclipse.persistence.testing.models.jpa.advanced.Loot;
import org.eclipse.persistence.testing.models.jpa.advanced.PhoneNumber;
import org.eclipse.persistence.testing.models.jpa.advanced.Project;
import org.eclipse.persistence.testing.models.jpa.advanced.Quantity;
import org.eclipse.persistence.testing.models.jpa.advanced.SmallProject;
import org.eclipse.persistence.testing.models.jpa.advanced.Violation;
import org.eclipse.persistence.testing.models.jpa.advanced.ViolationCode;
import org.eclipse.persistence.testing.models.jpa.advanced.Violation.ViolationID;
import org.eclipse.persistence.testing.models.jpa.advanced.ViolationCode.ViolationCodeId;
import org.eclipse.persistence.testing.models.jpa.advanced.HockeyPuck;
import org.eclipse.persistence.testing.models.jpa.advanced.HockeyRink;
import org.eclipse.persistence.testing.models.jpa.advanced.HockeySponsor;
import org.eclipse.persistence.testing.models.jpa.advanced.additionalcriteria.Bolt;
import org.eclipse.persistence.testing.models.jpa.advanced.additionalcriteria.Eater;
import org.eclipse.persistence.testing.models.jpa.advanced.additionalcriteria.Nut;
import org.eclipse.persistence.testing.models.jpa.advanced.additionalcriteria.Rabbit;
import org.eclipse.persistence.testing.models.jpa.advanced.additionalcriteria.RabbitFoot;
import org.eclipse.persistence.testing.models.jpa.advanced.additionalcriteria.Sandwich;
import org.eclipse.persistence.testing.models.jpa.advanced.additionalcriteria.School;
import org.eclipse.persistence.testing.models.jpa.advanced.additionalcriteria.Student;
import org.eclipse.persistence.tools.schemaframework.SchemaManager;
import org.eclipse.persistence.tools.schemaframework.StoredFunctionDefinition;
/**
* This test suite tests EclipseLink JPA annotations extensions.
*/
public class AdvancedJPAJunitTest extends JUnitTestCase {
private static int empId;
private static int penelopeId;
private static int deptId;
private static int buyerId;
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 static String newResponsibility = "The most useless responsibility ever.";
public AdvancedJPAJunitTest() {
super();
}
public AdvancedJPAJunitTest(String name) {
super(name);
}
public void setUp() {
super.setUp();
clearCache();
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.setName("AdvancedJPAJunitTest");
suite.addTest(new AdvancedJPAJunitTest("testSetup"));
suite.addTest(new AdvancedJPAJunitTest("testRelationshipReadDuringClone"));
suite.addTest(new AdvancedJPAJunitTest("testExistenceCheckingSetting"));
suite.addTest(new AdvancedJPAJunitTest("testJoinColumnForeignKeyFieldLength"));
suite.addTest(new AdvancedJPAJunitTest("testJoinFetchAnnotation"));
suite.addTest(new AdvancedJPAJunitTest("testVerifyEmployeeCacheSettings"));
suite.addTest(new AdvancedJPAJunitTest("testVerifyEmployeeCustomizerSettings"));
suite.addTest(new AdvancedJPAJunitTest("testUpdateEmployee"));
suite.addTest(new AdvancedJPAJunitTest("testVerifyUpdatedEmployee"));
suite.addTest(new AdvancedJPAJunitTest("testCreateNewBuyer"));
suite.addTest(new AdvancedJPAJunitTest("testVerifyNewBuyer"));
suite.addTest(new AdvancedJPAJunitTest("testBuyerOptimisticLocking"));
suite.addTest(new AdvancedJPAJunitTest("testOptimisticLockExceptionOnMerge"));
suite.addTest(new AdvancedJPAJunitTest("testOptimisticLockExceptionOnMergeWithAssumeExists"));
suite.addTest(new AdvancedJPAJunitTest("testVersionUpdateForOwnedMappings"));
suite.addTest(new AdvancedJPAJunitTest("testGiveFredAnObjectTypeConverterChange"));
suite.addTest(new AdvancedJPAJunitTest("testUpdatePenelopesPhoneNumberStatus"));
suite.addTest(new AdvancedJPAJunitTest("testRemoveJillWithPrivateOwnedPhoneNumbers"));
suite.addTest(new AdvancedJPAJunitTest("testCreateNewEquipment"));
suite.addTest(new AdvancedJPAJunitTest("testAddNewEquipmentToDepartment"));
suite.addTest(new AdvancedJPAJunitTest("testRemoveDepartmentWithPrivateOwnedEquipment"));
suite.addTest(new AdvancedJPAJunitTest("testUpdateReadOnlyEquipmentCode"));
suite.addTest(new AdvancedJPAJunitTest("testNamedStoredProcedureQuery"));
suite.addTest(new AdvancedJPAJunitTest("testNamedStoredProcedureQueryByIndex"));
suite.addTest(new AdvancedJPAJunitTest("testNamedStoredProcedureQueryInOut"));
suite.addTest(new AdvancedJPAJunitTest("testNamedStoredProcedureQueryWithRawData"));
suite.addTest(new AdvancedJPAJunitTest("testModifyNamedStoredProcedureQueryWithRawData"));
suite.addTest(new AdvancedJPAJunitTest("testNamedStoredProcedureQueryWithResultSetMapping"));
suite.addTest(new AdvancedJPAJunitTest("testNamedStoredProcedureQueryWithResultSetFieldMapping"));
suite.addTest(new AdvancedJPAJunitTest("testNamedFunction"));
suite.addTest(new AdvancedJPAJunitTest("testMethodBasedTransformationMapping"));
suite.addTest(new AdvancedJPAJunitTest("testClassBasedTransformationMapping"));
suite.addTest(new AdvancedJPAJunitTest("testProperty"));
suite.addTest(new AdvancedJPAJunitTest("testBackpointerOnMerge"));
suite.addTest(new AdvancedJPAJunitTest("testUnidirectionalPersist"));
suite.addTest(new AdvancedJPAJunitTest("testUnidirectionalUpdate"));
suite.addTest(new AdvancedJPAJunitTest("testUnidirectionalFetchJoin"));
suite.addTest(new AdvancedJPAJunitTest("testUnidirectionalTargetLocking_AddRemoveTarget"));
suite.addTest(new AdvancedJPAJunitTest("testUnidirectionalTargetLocking_DeleteSource"));
suite.addTest(new AdvancedJPAJunitTest("testMapBuildReferencesPKList"));
suite.addTest(new AdvancedJPAJunitTest("testListBuildReferencesPKList"));
suite.addTest(new AdvancedJPAJunitTest("testEnumeratedPrimaryKeys"));
suite.addTest(new AdvancedJPAJunitTest("testAttributeOverrideToMultipleSameDefaultColumnName"));
suite.addTest(new AdvancedJPAJunitTest("testTransparentIndirectionValueHolderSessionReset"));
suite.addTest(new AdvancedJPAJunitTest("testTransparentIndirectionQuerySessionReset"));
if (!isJPA10()) {
// These tests use JPA 2.0 entity manager API
suite.addTest(new AdvancedJPAJunitTest("testQueryGetParameter"));
suite.addTest(new AdvancedJPAJunitTest("testAdditionalCriteriaModelPopulate"));
suite.addTest(new AdvancedJPAJunitTest("testAdditionalCriteria"));
suite.addTest(new AdvancedJPAJunitTest("testAdditionalCriteriaWithParameterFromEM1"));
suite.addTest(new AdvancedJPAJunitTest("testAdditionalCriteriaWithParameterFromEM2"));
suite.addTest(new AdvancedJPAJunitTest("testAdditionalCriteriaWithParameterFromEMF"));
suite.addTest(new AdvancedJPAJunitTest("testComplexAdditionalCriteria"));
suite.addTest(new AdvancedJPAJunitTest("testAdditionalCriteriaBetweenEntities"));
suite.addTest(new AdvancedJPAJunitTest("testAdditionalCriteriaWithSubQuery"));
// Run this test only when the JPA 2.0 specification is enabled on the server, or we are in SE mode with JPA 2.0 capability
suite.addTest(new AdvancedJPAJunitTest("testMetamodelMinimalSanityTest"));
suite.addTest(new AdvancedJPAJunitTest("testInvalidateAndRefreshEmbeddableParent"));
}
return suite;
}
/**
* The setup is done as a test, both to record its failure, and to allow execution in the server.
*/
public void testSetup() {
ServerSession session = JUnitTestCase.getServerSession();
new AdvancedTableCreator().replaceTables(session);
// The EquipmentCode class 'should' be set to read only. We want
// to be able to create a couple in the Employee populator, so
// force the read only to false. If EquipmentCode is not
// actually read only, don't worry, we set the original read
// only value back on the descriptor and the error will be
// caught in a later test in this suite.
ClassDescriptor descriptor = session.getDescriptor(EquipmentCode.class);
boolean shouldBeReadOnly = descriptor.shouldBeReadOnly();
descriptor.setShouldBeReadOnly(false);
// Populate the database with our examples.
EmployeePopulator employeePopulator = new EmployeePopulator();
employeePopulator.buildExamples();
employeePopulator.persistExample(session);
descriptor.setShouldBeReadOnly(shouldBeReadOnly);
clearCache();
//create stored function when database supports it
if (supportsStoredFunctions()) {
SchemaManager schema = new SchemaManager(session);
schema.replaceObject(buildStoredFunction());
}
}
public StoredFunctionDefinition buildStoredFunction() {
StoredFunctionDefinition func = new StoredFunctionDefinition();
func.setName("StoredFunction_In");
func.addArgument("P_IN", Long.class);
func.setReturnType(Long.class);
func.addStatement("RETURN P_IN * 1000");
return func;
}
/* Test named function 'StoredFunction_In'*/
public void testNamedFunction() {
if (!supportsStoredFunctions()) {
warning("this test is not suitable for running on dbs that don't support stored function");
return;
}
EntityManager em = createEntityManager();
Query query;
try {
query = em.createNamedQuery("StoredFunction_In");
query.setParameter("P_IN", 1);
int result = (Integer)query.getSingleResult();
if (result != 1000) {
fail("Incorrect result returned:" + result);
}
} finally {
closeEntityManager(em);
}
}
/**
* Bug 322916
*/
public void testQueryGetParameter() {
EntityManager em = createEntityManager();
try {
Query query = em.createQuery("select e from Employee e where e.salary = :sal").setParameter("sal", 1000);
query.getParameter("sal");
} catch (Exception e) {
fail("Get parameter on test failed: " + e);
} finally {
closeEntityManager(em);
}
}
/**
* 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("findJPQLSchools").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 {
beginTransaction(em);
// 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 Student s").getResultList();
assertTrue("Incorrect number of students were returned [" + students.size() + "], expected [8]", students.size() == 8);
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 parameter.
*/
public void testAdditionalCriteriaWithParameterFromEM2() {
EntityManager em = createEntityManager();
try {
beginTransaction(em);
// 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 Student s").getResultList();
assertTrue("Incorrect number of students were returned [" + students.size() + "], expected [18]", students.size() == 18);
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);
}
public void testMapBuildReferencesPKList(){
EntityManager em = createEntityManager();
beginTransaction(em);
ClassDescriptor descriptor;
AbstractSession session = (AbstractSession) JpaHelper.getEntityManager(em).getActiveSession();
descriptor = session.getDescriptorForAlias("ADV_DEPT");
Department dept = (Department) em.createQuery("SELECT d FROM ADV_DEPT d WHERE d.equipment IS NOT EMPTY").getResultList().get(0);
ForeignReferenceMapping mapping = (ForeignReferenceMapping) descriptor.getMappingForAttributeName("equipment");
Object[] pks = mapping.buildReferencesPKList(dept, mapping.getAttributeValueFromObject(dept), session);
assertTrue ("PK list is of incorrect size. pks.size: " + pks.length + " expected: " + (dept.getEquipment().size() * 2), pks.length == (dept.getEquipment().size() * 2));
Map<Integer, Equipment> equipments = (Map<Integer, Equipment>) mapping.valueFromPKList(pks, session);
assertTrue("ValueFromPKList returned list of different size from actual entity.", equipments.size() == dept.getEquipment().size());
for (Equipment equip : dept.getEquipment().values()){
assertTrue("Equipment not found in ValueFromPKList list", equipments.containsKey(equip.getId()));
}
rollbackTransaction(em);
}
public void testListBuildReferencesPKList(){
EntityManager em = createEntityManager();
beginTransaction(em);
Jigsaw jigsaw = new Jigsaw();
for (int i = 1; i < 11; i++) {
jigsaw.addPiece(new JigsawPiece(i));
}
em.persist(jigsaw);
em.flush();
clearCache();
AbstractSession session = (AbstractSession) JpaHelper.getEntityManager(em).getActiveSession();
ClassDescriptor descriptor = session.getDescriptorForAlias("Jigsaw");
Jigsaw foundJigsaw = (Jigsaw) em.find(Jigsaw.class, jigsaw.getId());
int expectedNumber = foundJigsaw.getPieces().size();
ForeignReferenceMapping mapping = (ForeignReferenceMapping) descriptor.getMappingForAttributeName("pieces");
Object[] pks = mapping.buildReferencesPKList(foundJigsaw, mapping.getAttributeValueFromObject(foundJigsaw), session);
assertEquals("PK list is of incorrect size", expectedNumber, pks.length);
List<JigsawPiece> elements = (List<JigsawPiece>) mapping.valueFromPKList(pks, session);
assertEquals("ValueFromPKList returned list of different size from actual entity.", expectedNumber, elements.size());
for (JigsawPiece element : elements){
assertTrue("Entity id " + element.getId() + " not found in ValueFromPKList list", foundJigsaw.getPieces().contains(element));
}
rollbackTransaction(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 Student 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 {
beginTransaction(em);
em.setProperty("NUT_SIZE", 8);
em.setProperty("NUT_COLOR", "Grey");
List bolts = em.createQuery("SELECT b from Bolt b").getResultList();
assertTrue("Incorrect number of bolts were returned [" + bolts.size() + "], expected [2]", bolts.size() == 2);
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 additional criteria when used on two entities that have a
* relationship between the two.
*/
public void testAdditionalCriteriaBetweenEntities() {
EntityManager em = createEntityManager("additional-criteria");
try {
beginTransaction(em);
em.setProperty("SANDWICH_DESCRIPTION", "%hot%");
em.setProperty("EATER_NAME", "%Glutton%");
Sandwich sandwich = new Sandwich();
sandwich.setName("The Inferno");
sandwich.setDescription("A hot and spicy crazy concoction");
em.persist(sandwich);
Eater eater = new Eater();
eater.setName("Glutton for spicy");
eater.setSandwhich(sandwich);
em.persist(eater);
commitTransaction(em);
} catch (RuntimeException e) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
// Re-throw exception to ensure stacktrace appears in test result.
throw e;
} finally {
closeEntityManager(em);
}
}
/**
* Test additional criteria when using a sub query.
*/
public void testAdditionalCriteriaWithSubQuery() {
EntityManager em = createEntityManager("additional-criteria");
try {
beginTransaction(em);
Rabbit rabbit = new Rabbit();
rabbit.setName("Bugs");
em.persist(rabbit);
RabbitFoot rabbitFoot = new RabbitFoot();
rabbitFoot.setCaption("Caption of Bugs");
rabbitFoot.setRabbitId(rabbit.getId());
em.persist(rabbitFoot);
commitTransaction(em);
em.clear();
clearCache("additional-criteria");
List<Eater> rabbits = em.createQuery("select this from Rabbit this").getResultList();
} catch (RuntimeException e) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
// Re-throw exception to ensure stacktrace appears in test result.
throw e;
} finally {
closeEntityManager(em);
}
}
/**
* Bug 328114
*/
public void testAttributeOverrideToMultipleSameDefaultColumnName() {
EntityManager em = createEntityManager();
try {
beginTransaction(em);
Loot loot = new Loot();
Bag bag = new Bag();
Quantity quantity = new Quantity();
quantity.value = 11;
bag.quantity = quantity;
Cost cost = new Cost();
cost.value = 5.99;
bag.cost = cost;
loot.bag = bag;
em.persist(loot);
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);
}
/**
* This test performs minimal sanity testing on the advanced JPA model
* in order to verify metamodel creation.<p>
* See the metamodel test package suite for full regression tests.
* See SVN rev# 5124
* http://fisheye2.atlassian.com/changelog/~author=mobrien/eclipselink/?cs=5124
*/
public void testMetamodelMinimalSanityTest() {
EntityManager em = createEntityManager();
// pre-clear metamodel to enable test reentry (SE only - not EE)
if(!this.isOnServer()) {
((EntityManagerFactoryDelegate)((EntityManagerImpl)em).getEntityManagerFactory()).setMetamodel(null);
}
Metamodel metamodel = em.getMetamodel();
// get declared attributes
EntityType<LargeProject> entityLargeProject = metamodel.entity(LargeProject.class);
Set<Attribute<LargeProject, ?>> declaredAttributes = entityLargeProject.getDeclaredAttributes();
assertTrue(declaredAttributes.size() > 0); // instead of a assertEquals(1, size) for future compatibility with changes to Buyer
// check that getDeclaredAttribute and getDeclaredAttributes return the same attribute
Attribute<LargeProject, ?> budgetAttribute = entityLargeProject.getDeclaredAttribute("budget");
assertNotNull(budgetAttribute);
Attribute<LargeProject, ?> budgetSingularAttribute = entityLargeProject.getDeclaredSingularAttribute("budget");
assertNotNull(budgetSingularAttribute);
assertEquals(budgetSingularAttribute, budgetAttribute);
assertTrue(declaredAttributes.contains(budgetSingularAttribute));
// check the type
Class budgetClass = budgetSingularAttribute.getJavaType();
// Verify whether we expect a boxed class or not
assertEquals(double.class, budgetClass);
//assertEquals(Double.class, budgetClass);
// Test LargeProject.budget.buyingDays
// Check an EnumSet on an Entity
EntityType<Buyer> entityBuyer = metamodel.entity(Buyer.class);
// public enum Weekdays { SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY }
// private EnumSet<Weekdays> buyingDays;
assertNotNull(entityBuyer);
// check persistence type
assertEquals(PersistenceType.ENTITY, entityBuyer.getPersistenceType());
assertEquals(Buyer.class, entityBuyer.getJavaType());
// verify EnumSet is a SingularAttribute
Attribute buyingDaysAttribute = entityBuyer.getAttribute("buyingDays");
assertNotNull(buyingDaysAttribute);
// Check persistent attribute type
assertEquals(PersistentAttributeType.BASIC, buyingDaysAttribute.getPersistentAttributeType());
// Non-spec check on the attribute impl type
// EnumSet is not a Set in the Metamodel - it is a treated as a BasicType single object (SingularAttributeType)
// BasicTypeImpl@8980685:EnumSet [ javaType: class java.util.EnumSet]
assertFalse(((SingularAttributeImpl)buyingDaysAttribute).isPlural());
BindableType buyingDaysElementBindableType = ((SingularAttributeImpl)buyingDaysAttribute).getBindableType();
assertEquals(BindableType.SINGULAR_ATTRIBUTE, buyingDaysElementBindableType);
SingularAttribute<? super Buyer, EnumSet> buyingDaysSingularAttribute = entityBuyer.getSingularAttribute("buyingDays", EnumSet.class);
assertNotNull(buyingDaysSingularAttribute);
assertFalse(buyingDaysSingularAttribute.isCollection());
// http://wiki.eclipse.org/EclipseLink/Development/JPA_2.0/metamodel_api#DI_74:_20090909:_Implement_IdentifiableType.hasSingleIdAttribute.28.29
// Check for Id that exists
boolean expectedIAExceptionThrown = false;
boolean hasSingleIdAttribute = false;
try {
hasSingleIdAttribute = entityBuyer.hasSingleIdAttribute();
} catch (IllegalArgumentException iae) {
//iae.printStackTrace();
expectedIAExceptionThrown = true;
}
assertFalse(expectedIAExceptionThrown);
assertTrue(hasSingleIdAttribute);
// Verify that the BasicMap Buyer.creditCards is picked up properly
//* @param <X> The type the represented Map belongs to
//* @param <K> The type of the key of the represented Map
//* @param <V> The type of the value of the represented Map
//public class MapAttributeImpl<X, K, V> extends PluralAttributeImpl<X, java.util.Map<K, V>, V>
Attribute buyerCreditCards = entityBuyer.getAttribute("creditCards");
assertNotNull(buyerCreditCards);
assertTrue(buyerCreditCards.isCollection());
assertTrue(buyerCreditCards instanceof MapAttributeImpl);
MapAttribute<? super Buyer, ?, ?> buyerCreditCardsMap = entityBuyer.getMap("creditCards");
// Verify owning type
assertNotNull(buyerCreditCardsMap);
assertEquals(entityBuyer, buyerCreditCardsMap.getDeclaringType());
// Verify Map Key
assertEquals(String.class, buyerCreditCardsMap.getKeyJavaType());
// Verify Map Value
assertEquals(Long.class, buyerCreditCardsMap.getElementType().getJavaType());
}
/**
* Verifies that existence-checking metadata is correctly processed.
*/
public void testExistenceCheckingSetting() {
ServerSession session = JUnitTestCase.getServerSession();
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);
}
public void testJoinColumnForeignKeyFieldLength() {
ServerSession session = JUnitTestCase.getServerSession();
ClassDescriptor employeeDescriptor = session.getDescriptor(Employee.class);
ClassDescriptor buyerDescriptor = session.getDescriptor(Buyer.class);
//////////////////// Test fk from a secondary table ////////////////////
DatabaseTable secondaryTable = employeeDescriptor.getTable("CMP3_SALARY");
Map<DatabaseField, DatabaseField> keys = employeeDescriptor.getAdditionalTablePrimaryKeyFields().get(secondaryTable);
for (DatabaseField pkField : keys.keySet()) {
DatabaseField fkField = keys.get(pkField);
assertTrue("The secondary table foreign field [" + fkField.getName() + "(" + fkField.getLength() + ")] did not have the same length as the primary key field [" + pkField.getName() + "(" + pkField.getLength() + ")]", fkField.getLength() == pkField.getLength());
}
////////////////////////// Test a M-1 mapping //////////////////////////
DatabaseMapping mapping = employeeDescriptor.getMappingForAttributeName("address");
assertNotNull("The address mapping from Employee was not found", mapping);
assertTrue("The address mapping is no longer a one to one mapping", mapping.isOneToOneMapping());
keys = ((OneToOneMapping) mapping).getSourceToTargetKeyFields();
for (DatabaseField fkField : keys.keySet()) {
DatabaseField pkField = keys.get(fkField);
assertTrue("The address mapping foreign field [" + fkField.getName() + "(" + fkField.getLength() + ")] did not have the same length as the primary key field [" + pkField.getName() + "(" + pkField.getLength() + ")]", fkField.getLength() == pkField.getLength());
}
////////////////// Test a unidirectional 1-M mapping ///////////////////
mapping = employeeDescriptor.getMappingForAttributeName("dealers");
assertNotNull("The dealers mapping from Employee was not found", mapping);
assertTrue("The dealers mapping is no longer a unidirectional one to many mapping", mapping.isUnidirectionalOneToManyMapping());
keys = ((UnidirectionalOneToManyMapping) mapping).getTargetForeignKeysToSourceKeys();
for (DatabaseField fkField : keys.keySet()) {
DatabaseField pkField = keys.get(fkField);
assertTrue("The dealers mapping foreign key field [" + fkField.getName() + "(" + fkField.getLength() + ")] did not have the same length as the primary key field [" + pkField.getName() + "(" + pkField.getLength() + ")]", fkField.getLength() == pkField.getLength());
}
////////////////////////// Test a M-M mapping //////////////////////////
mapping = employeeDescriptor.getMappingForAttributeName("projects");
assertNotNull("The projects mapping from Employee was not found", mapping);
assertTrue("The projects mapping is no longer a many to many mapping", mapping.isManyToManyMapping());
Vector<DatabaseField> sourceKeys = ((ManyToManyMapping) mapping).getSourceKeyFields();
Vector<DatabaseField> sourceRelationKeys = ((ManyToManyMapping) mapping).getSourceRelationKeyFields();
for (int i = 0; i < sourceKeys.size(); i++) {
DatabaseField sourcePrimaryKey = sourceKeys.get(i);
DatabaseField sourceRelationForeignKey = sourceRelationKeys.get(i);
assertTrue("The projects mapping source relation foreign key field [" + sourceRelationForeignKey.getName() + "(" + sourceRelationForeignKey.getLength() + ")] did not have the same length as the source primary key field [" + sourcePrimaryKey.getName() + "(" + sourcePrimaryKey.getLength() + ")]", sourcePrimaryKey.getLength() == sourceRelationForeignKey.getLength());
}
Vector<DatabaseField> targetKeys = ((ManyToManyMapping) mapping).getSourceKeyFields();
Vector<DatabaseField> targetRelationKeys = ((ManyToManyMapping) mapping).getSourceRelationKeyFields();
for (int i = 0; i < targetKeys.size(); i++) {
DatabaseField targetPrimaryKey = targetKeys.get(i);
DatabaseField targetRelationForeignKey = targetRelationKeys.get(i);
assertTrue("The projects mapping target relation foreign key field [" + targetRelationForeignKey.getName() + "(" + targetRelationForeignKey.getLength() + ")] did not have the same length as the target primary key field [" + targetPrimaryKey.getName() + "(" + targetPrimaryKey.getLength() + ")]", targetPrimaryKey.getLength() == targetRelationForeignKey.getLength());
}
//////////////////////// Test a basic collection ///////////////////////
mapping = employeeDescriptor.getMappingForAttributeName("responsibilities");
assertNotNull("The responsibilities mapping from Employee was not found", mapping);
assertTrue("The responsibilities mapping is no longer a direct collection mapping", mapping.isDirectCollectionMapping());
Vector<DatabaseField> primaryKeys = ((DirectCollectionMapping) mapping).getSourceKeyFields();
Vector<DatabaseField> foreignKeys = ((DirectCollectionMapping) mapping).getReferenceKeyFields();
for (int i = 0; i < primaryKeys.size(); i++) {
DatabaseField primaryKey = primaryKeys.get(i);
DatabaseField foreignKey = foreignKeys.get(i);
assertTrue("The responsibilities mapping foreign key field [" + foreignKey.getName() + "(" + foreignKey.getLength() + ")] did not have the same length as the source primary key field [" + primaryKey.getName() + "(" + primaryKey.getLength() + ")]", primaryKey.getLength() == foreignKey.getLength());
}
//////// Test an element collection mapping (direct collection) ////////
mapping = buyerDescriptor.getMappingForAttributeName("creditLines");
assertNotNull("The creditLines mapping from Buyer was not found", mapping);
assertTrue("The creditLines mapping is no longer an element collection mapping", mapping.isDirectCollectionMapping());
primaryKeys = ((DirectCollectionMapping) mapping).getSourceKeyFields();
foreignKeys = ((DirectCollectionMapping) mapping).getReferenceKeyFields();
for (int i = 0; i < primaryKeys.size(); i++) {
DatabaseField primaryKey = primaryKeys.get(i);
DatabaseField foreignKey = foreignKeys.get(i);
assertTrue("The creditLines mapping foreign key field [" + foreignKey.getName() + "(" + foreignKey.getLength() + ")] did not have the same length as the source primary key field [" + primaryKey.getName() + "(" + primaryKey.getLength() + ")]", primaryKey.getLength() == foreignKey.getLength());
}
// Items not directly tested: element collection using a map and basic map.
}
/**
* Verifies that settings from the Employee cache annotation have been set.
*/
public void testVerifyEmployeeCacheSettings() {
EntityManager em = createEntityManager("default1");
ClassDescriptor descriptor;
if (isOnServer()) {
descriptor = getServerSession("default1").getDescriptorForAlias("Employee");
} else {
descriptor = ((EntityManagerImpl) em).getServerSession().getDescriptorForAlias("Employee");
}
if (descriptor == null) {
fail("A descriptor for the Employee alias was not found in the default1 PU.");
} else {
assertTrue("Incorrect cache type() setting.", descriptor.getIdentityMapClass().equals(ClassConstants.SoftCacheWeakIdentityMap_Class));
assertTrue("Incorrect cache size() setting, was: " + descriptor.getIdentityMapSize() + " expected: 730.", descriptor.getIdentityMapSize() == 730);
assertFalse("Incorrect cache isolated() setting.", descriptor.isIsolated());
assertFalse("Incorrect cache alwaysRefresh() setting.", descriptor.shouldAlwaysRefreshCache());
// The diableHits() setting gets changed in the employee customizer.
// Its setting is checked in the test below.
CacheInvalidationPolicy policy = descriptor.getCacheInvalidationPolicy();
assertTrue("Incorrect cache expiry() policy setting.", policy instanceof TimeToLiveCacheInvalidationPolicy);
assertTrue("Incorrect cache expiry() setting.", ((TimeToLiveCacheInvalidationPolicy) policy).getTimeToLive() == 1000000);
assertTrue("Incorrect cache coordinationType() settting.", descriptor.getCacheSynchronizationType() == ClassDescriptor.INVALIDATE_CHANGED_OBJECTS);
}
closeEntityManager(em);
}
/**
* Verifies that settings from the EmployeeCustomizer have been set.
*/
public void testVerifyEmployeeCustomizerSettings() {
EntityManager em = createEntityManager();
ClassDescriptor descriptor = getServerSession().getDescriptorForAlias("Employee");
if (descriptor == null) {
fail("A descriptor for the Employee alias was not found.");
} else {
assertFalse("Disable cache hits was true. Customizer should have made it false.", descriptor.shouldDisableCacheHits());
}
closeEntityManager(em);
}
/**
* Verifies that the join-fetch annotation was read correctly.
*/
public void testJoinFetchAnnotation() {
ServerSession session = JUnitTestCase.getServerSession();
ClassDescriptor descriptor = session.getDescriptor(Employee.class);
if (((ForeignReferenceMapping)descriptor.getMappingForAttributeName("department")).getJoinFetch() != ForeignReferenceMapping.OUTER_JOIN) {
fail("JoinFetch annotation not read correctly for Employee.department.");
}
}
/**
* Tests:
* - BasicCollection mapping
* - Serialized Basic of type EnumSet.
* - BasicCollection that uses an Enum converter (by detection).
*/
public void testUpdateEmployee() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
EJBQueryImpl query = (EJBQueryImpl) em.createNamedQuery("findAllSQLEmployees");
Collection<Employee> employees = query.getResultCollection();
if (employees.isEmpty()) {
fail("No Employees were found. Test requires at least one Employee to be created in the EmployeePopulator.");
} else {
Employee emp = employees.iterator().next();
emp.addResponsibility(newResponsibility);
emp.setMondayToFridayWorkWeek();
empId = emp.getId();
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);
}
/**
* Verifies:
* - a BasicCollection mapping.
* - a BasicCollection that uses an Enum converter (by detection).
*/
public void testVerifyUpdatedEmployee() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
Employee emp = em.find(Employee.class, empId);
assertNotNull("The updated employee was not found.", emp);
boolean found = false;
for (String responsibility : (Collection<String>) emp.getResponsibilities()) {
if (responsibility.equals(newResponsibility)) {
found = true;
break;
}
}
commitTransaction(em);
assertTrue("The new responsibility was not added.", found);
assertTrue("The basic collection using enums was not persisted correctly.", emp.worksMondayToFriday());
} 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 testVersionUpdateForOwnedMappings(){
EntityManager em = createEntityManager();
beginTransaction(em);
try {
Employee emp = em.find(Employee.class, empId);
int currentVersion = emp.getVersion();
assertNotNull("The employee was not found for Id.", empId);
emp.getResponsibilities().add("UpdateVersionField");
commitTransaction(em);
assertTrue("Did not increment version for change to direct collection", emp.getVersion() == ++currentVersion);
beginTransaction(em);
emp = em.find(Employee.class, empId);
emp.getDealers().add(em.merge(new Dealer("update", "version")));
commitTransaction(em);
assertTrue("Did not increment version for change to uni-directional one to many with join table", emp.getVersion() == ++currentVersion);
beginTransaction(em);
emp = em.find(Employee.class, empId);
emp.getProjects().add(em.merge(new LargeProject("versionUpdate")));
commitTransaction(em);
assertTrue("Did not increment version for change to owned ManyToMany", emp.getVersion() == ++currentVersion);
} 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:
* - BasicMap mapping with a TypeConverter on the map value and an
* ObjectTypeConverter on the map key.
* - Basic with a custom converter
* - Serialized Basic of type EnumSet.
*/
public void testCreateNewBuyer() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
GoldBuyer buyer = new GoldBuyer();
buyer.setName("Guy Pelletier");
buyer.setGender("Made of testosterone");
buyer.setDescription("Loves to spend");
buyer.addVisa(visa);
buyer.addAmex(amex);
buyer.addDinersClub(diners);
buyer.addMastercard(mastercard);
buyer.addRoyalBankCreditLine(rbc);
buyer.addScotiabankCreditLine(scotia);
buyer.addTorontoDominionCreditLine(td);
buyer.addCanadianImperialCreditLine(cibc);
buyer.setSaturdayToSundayBuyingDays();
em.persist(buyer);
commitTransaction(em);
buyerId = buyer.getId();
} 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:
* - BasicMap mapping with a TypeConverter on the map value and an
* ObjectTypeConverter on the map key.
* - Basic with a custom converter
* - Serialized Basic of type EnumSet.
*/
public void testVerifyNewBuyer() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
GoldBuyer buyer = em.find(GoldBuyer.class, buyerId);
assertNotNull("The new buyer was not found", buyer);
assertTrue("Gender was not persisted correctly.", buyer.isMale());
assertTrue("Visa card did not persist correctly.", buyer.hasVisa(visa));
assertTrue("Amex card did not persist correctly.", buyer.hasAmex(amex));
assertTrue("Diners Club card did not persist correctly.", buyer.hasDinersClub(diners));
assertTrue("Mastercard card did not persist correctly.", buyer.hasMastercard(mastercard));
assertTrue("RBC credit line did not persist correctly.", buyer.hasRoyalBankCreditLine(rbc));
assertTrue("Scotia credit line did not persist correctly.", buyer.hasScotiabankCreditLine(scotia));
assertTrue("TD credit line did not persist correctly.", buyer.hasTorontoDominionCreditLine(td));
assertTrue("CIBC credit line did not persist correctly.", buyer.hasCanadianImperialCreditLine(cibc));
assertTrue("The serialized enum set was not persisted correctly.", buyer.buysSaturdayToSunday());
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);
}
/**
* Tests an OptimisticLocking policy set on Buyer.
*/
public void testBuyerOptimisticLocking() {
// Cannot create parallel entity managers in the server.
if (isOnServer()) {
return;
}
EntityManager em1 = createEntityManager();
EntityManager em2 = createEntityManager();
em1.getTransaction().begin();
em2.getTransaction().begin();
RuntimeException caughtException = null;
try {
GoldBuyer buyer1 = em1.find(GoldBuyer.class, buyerId);
GoldBuyer buyer2 = em2.find(GoldBuyer.class, buyerId);
buyer1.setName("Geezer");
buyer2.setName("Guyzer");
// Uses field locking, so need to update version.
buyer1.setVersion(buyer1.getVersion() + 1);
buyer2.setVersion(buyer2.getVersion() + 1);
em1.getTransaction().commit();
em2.getTransaction().commit();
em1.close();
em2.close();
} catch (RuntimeException e) {
caughtException = e;
if (em1.getTransaction().isActive()){
em1.getTransaction().rollback();
}
if (em2.getTransaction().isActive()){
em2.getTransaction().rollback();
}
em1.close();
em2.close();
}
if (caughtException == null) {
fail("Optimistic lock exception was not thrown.");
} else if (!(caughtException.getCause() instanceof javax.persistence.OptimisticLockException)) {
// Re-throw exception to ensure stacktrace appears in test result.
throw caughtException;
}
}
/**
* Tests an ObjectTypeConverter on a direct to field mapping.
*/
public void testGiveFredAnObjectTypeConverterChange() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
EJBQueryImpl query = (EJBQueryImpl) em.createNamedQuery("findAllEmployeesByFirstName");
query.setParameter("firstname", "Fred");
Collection<Employee> employees = query.getResultCollection();
if (employees.isEmpty()) {
fail("No employees named Fred were found. Test requires at least one Fred to be created in the EmployeePopulator.");
} else {
Employee fred = employees.iterator().next();
fred.setFemale();
fred.setFirstName("Penelope");
penelopeId = fred.getId();
commitTransaction(em);
// Clear cache and clear the entity manager
clearCache();
em.clear();
Employee penelope = em.find(Employee.class, penelopeId);
assertTrue("Fred's ObjectTypeConverter change to Penelope didn't occur.", penelope.isFemale());
}
} 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 BasicCollection on an entity that uses a composite primary key.
*/
public void testUpdatePenelopesPhoneNumberStatus() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
Employee emp = em.find(Employee.class, penelopeId);
assertNotNull("The employee with id: [" + penelopeId + "] was not found.", emp);
for (PhoneNumber phoneNumber : emp.getPhoneNumbers()) {
phoneNumber.addStatus(PhoneNumber.PhoneStatus.ACTIVE);
phoneNumber.addStatus(PhoneNumber.PhoneStatus.ASSIGNED);
}
commitTransaction(em);
// Clear cache and clear the entity manager
clearCache();
em.clear();
Employee emp2 = em.find(Employee.class, penelopeId);
for (PhoneNumber phone : emp2.getPhoneNumbers()) {
assertTrue("", phone.getStatus().contains(PhoneNumber.PhoneStatus.ACTIVE));
assertTrue("", phone.getStatus().contains(PhoneNumber.PhoneStatus.ASSIGNED));
}
} catch (RuntimeException e) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
// Re-throw exception to ensure stacktrace appears in test result.
throw e;
}
closeEntityManager(em);
}
/**
* Remove an object from the shared cache as if garbage collected
* NPE will occur when it is read in using the CacheStoreMode.BYPASS setting outside a transaction.
*/
public void testReadingEntityGarbageCollectedFromSharedCache(){
EntityManager em = createEntityManager();
Employee emp = (Employee)em.createQuery("Select e from Employee e").getResultList().get(0);
em.clear();
clearCache();
// CacheKey key = this.getServerSession().getIdentityMapAccessorInstance().getCacheKeyForObject(emp);
// key.setObject(null);
try{
//query for the shared object that has a cachekey but was garbage collected from the shared cache
Query q = em.createQuery("Select f from Employee f where f.id ="+emp.getId());
//only seems to reproduce with this setting and not in an early transaction
q.setHint(QueryHints.CACHE_STORE_MODE, CacheStoreMode.BYPASS);
try {
Employee clone = (Employee)q.getSingleResult();
clone.toString();
}catch (java.lang.NullPointerException e){
this.fail("NPE occured building an Entity whos reference in the shared cache was garbage collected: "+e);
}
}finally {
if (this.isTransactionActive(em)) {
this.rollbackTransaction(em);
}
this.getServerSession().getIdentityMapAccessorInstance().initializeAllIdentityMaps();
}
}
/**
* Tests a @PrivateOwned @OneToMany mapping.
*/
public void testRemoveJillWithPrivateOwnedPhoneNumbers() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
EJBQueryImpl query = (EJBQueryImpl) em.createNamedQuery("findAllEmployeesByFirstName");
query.setParameter("firstname", "Jill");
Collection<Employee> employees = query.getResultCollection();
if (employees.isEmpty()) {
fail("No employees named Jill were found. Test requires at least one Jill to be created in the EmployeePopulator.");
} else {
Employee jill = employees.iterator().next();
Collection<PhoneNumber> phoneNumbers = jill.getPhoneNumbers();
if (phoneNumbers.isEmpty()) {
fail("Jill does not have any phone numbers. Test requires that Jill have atleast one phone number created in the EmployeePopulator.");
}
// Re-assign her managed employees and remove from her list.
for (Employee employee : jill.getManagedEmployees()) {
employee.setManager(jill.getManager());
}
jill.getManagedEmployees().clear();
int jillId = jill.getId();
em.remove(jill);
commitTransaction(em);
assertNull("Jill herself was not removed.", em.find(Employee.class, jillId));
for (PhoneNumber phoneNumber : phoneNumbers) {
assertNull("Jill's phone numbers were not deleted.", em.find(PhoneNumber.class, phoneNumber.buildPK()));
}
}
} catch (RuntimeException e) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
// Re-throw exception to ensure stacktrace appears in test result.
throw e;
}
closeEntityManager(em);
}
/**
* Creates some new equipment objects.
*/
public void testCreateNewEquipment() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
// Persist some equipment.
Equipment equip1 = new Equipment();
equip1.setDescription("Toaster");
em.persist(equip1);
Equipment equip2 = new Equipment();
equip1.setDescription("Bucket");
em.persist(equip2);
Equipment equip3 = new Equipment();
equip1.setDescription("Broom");
em.persist(equip3);
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);
}
/**
* Tests adding objects to a 1-M mapping that uses a map.
*/
public void testAddNewEquipmentToDepartment() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
EJBQueryImpl query = (EJBQueryImpl) em.createNamedQuery("findAllSQLEquipment");
Collection<Equipment> equipment = query.getResultCollection();
if (equipment.isEmpty()) {
fail("No Equipment was found. testCreateNewEquipment should have created new equipment and should have run before this test.");
} else {
Department department = new Department();
department.setName("Department with equipment");
for (Equipment e : equipment) {
department.addEquipment(e);
}
em.persist(department);
deptId = department.getId();
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);
}
/**
* Tests that backpointers are not changed after a merge operation.
*/
public void testBackpointerOnMerge() {
EntityManager em = createEntityManager();
try {
beginTransaction(em);
// create a new department
Department department = new Department();
department.setName("Football");
// persist the department
em.persist(department);
commitTransaction(em);
closeEntityManager(em);
// add equipment to the department
em = createEntityManager();
beginTransaction(em);
Equipment equipment = new Equipment();
equipment.setDescription("Shields & Dummies");
department.addEquipment(equipment);
em.merge(department);
commitTransaction(em);
closeEntityManager(em);
assertTrue(department.getEquipment().get(0) == equipment);
assertEquals(System.identityHashCode(department.getEquipment().get(0)), System.identityHashCode(equipment));
assertEquals(department.getId(), equipment.getDepartment().getId());
assertTrue("The department instance (backpointer) from equipment was modified after merge.", department == equipment.getDepartment());
assertEquals("The department instance (backpointer) from equipment was modified after merge.", System.identityHashCode(department), System.identityHashCode(equipment.getDepartment()));
} catch (RuntimeException e) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
throw e;
}
}
/**
* Tests a @NamedStoredProcedureQuery.
*/
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();
Address address2 = (Address) em.createNamedQuery("SProcAddress").setParameter("ADDRESS_ID", address1.getID()).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
assertTrue("Address build correctly using stored procedure", (address2.getID() == address1.getID()));
assertTrue("Address build correctly using stored procedure", (address2.getStreet().equals(address1.getStreet())));
assertTrue("Address build correctly using stored procedure", (address2.getCountry().equals(address1.getCountry())));
assertTrue("Address build correctly using stored procedure", (address2.getProvince().equals(address1.getProvince())));
} 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 @NamedStoredProcedureQuery using indexed parameters.
*/
public void testNamedStoredProcedureQueryByIndex() {
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();
Address address2 = (Address) em.createNamedQuery("SProcAddressByIndex").setParameter("ADDRESS_ID", address1.getID()).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
assertTrue("Address build correctly using stored procedure", (address2.getID() == address1.getID()));
assertTrue("Address build correctly using stored procedure", (address2.getStreet().equals(address1.getStreet())));
assertTrue("Address build correctly using stored procedure", (address2.getCountry().equals(address1.getCountry())));
assertTrue("Address build correctly using stored procedure", (address2.getProvince().equals(address1.getProvince())));
} 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 @NamedStoredProcedureQuery using a result-set mapping.
* 304400: Note: this test does not actually test a ResultSet return - it uses output parameters.
* To enable ResultSet testing - set returnsResultSet=true via orm.xml, annotation or via program call like the the core tests.
*/
public void testNamedStoredProcedureQueryWithResultSetMapping() {
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();
Address address2 = (Address) em.createNamedQuery("SProcAddressWithResultSetMapping").setParameter("address_id_v", address1.getID()).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
assertTrue("Address not found using stored procedure", (address2.getID() == address1.getID()));
} 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 @NamedStoredProcedureQuery using a result-set mapping.
* 304400: Note: this test does not actually test a ResultSet return - it uses output parameters.
* To enable ResultSet testing - set returnsResultSet=true via orm.xml, annotation or via program call like the the core tests.
*/
public void testNamedStoredProcedureQueryWithResultSetFieldMapping() {
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: we do not need to clear the cache for non-entity returns
Object[] values = (Object[]) em.createNamedQuery("SProcAddressWithResultSetFieldMapping").setParameter("address_id_v", address1.getID()).getSingleResult();
assertTrue("Address data not found or returned using stored procedure", ((values!=null) && (values.length==6)) );
assertNotNull("No results returned from store procedure call", values[1]);
assertTrue("Address not found using stored procedure", address1.getStreet().equals(values[1]));
} 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 @NamedStoredProcedureQuery.
*/
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("SProcInOut").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
assertTrue("Address not found using stored procedure", address1.getID() == address2.getID());
assertTrue("Address.street data returned doesn't match persisted address.street", address1.getStreet().equalsIgnoreCase(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 @NamedStoredProcedureQuery that returns raw data
* bug 254946
*/
public void testNamedStoredProcedureQueryWithRawData() {
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: we do not need to clear the cache for non-entity returns
Query aQuery = em.createNamedQuery("SProcInOutReturningRawData").setParameter("ADDRESS_ID", address1.getID());
Object[] objectdata = (Object[])aQuery.getSingleResult();
assertTrue("Address data not found or returned using stored procedure", ((objectdata!=null)&& (objectdata.length==2)) );
assertTrue("Address Id data returned doesn't match persisted address", (address1.getID() == ((Integer)objectdata[0]).intValue()) );
assertTrue("Address Street data returned doesn't match persisted address", ( address1.getStreet().equals(objectdata[1] )) );
} 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 an OptimisticLockingException is thrown when calling merge a detached and removed object.
* bug 272704
*/
public void testOptimisticLockExceptionOnMerge() {
EntityManager em1 = createEntityManager();
beginTransaction(em1);
RuntimeException caughtException = null;
try {
Employee emp = new Employee();
emp.setLastName("OptimisticLockExceptionOnMerge");
emp.setVersion(10);
em1.persist(emp);
commitTransaction(em1);
closeEntityManager(em1);
em1 = createEntityManager();
beginTransaction(em1);
emp = em1.find(Employee.class, emp.getId());
em1.remove(emp);
commitTransaction(em1);
closeEntityManager(em1);
em1 = createEntityManager();
beginTransaction(em1);
//this is expected to throw an OptimisticLockException, because the version is >1
em1.merge(emp);
commitTransaction(em1);
} catch (RuntimeException e) {
caughtException = e;
if (isTransactionActive(em1)){
rollbackTransaction(em1);
}
}
closeEntityManager(em1);
if (caughtException == null) {
fail("Optimistic lock exception was not thrown.");
} else if (!(caughtException instanceof javax.persistence.OptimisticLockException)) {
// Re-throw exception to ensure stacktrace appears in test result.
throw caughtException;
}
}
/**
* Tests an OptimisticLockingException is thrown when calling merge a detached and removed object.
* bug 272704
*/
public void testOptimisticLockExceptionOnMergeWithAssumeExists() {
org.eclipse.persistence.sessions.Project project = getServerSession().getProject();
ClassDescriptor descriptor = project.getDescriptor(Employee.class);
int existencePolicy = descriptor.getQueryManager().getDoesExistQuery().getExistencePolicy();
descriptor.getQueryManager().assumeExistenceForDoesExist();
try {
testOptimisticLockExceptionOnMerge();
} finally {
descriptor.getQueryManager().getDoesExistQuery().setExistencePolicy(existencePolicy);
}
}
/**
* Tests a @NamedStoredProcedureQuery that returns raw data using executeUpdate().
*/
public void testModifyNamedStoredProcedureQueryWithRawData() {
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);
beginTransaction(em);
em.createNamedQuery("SProcInOutReturningRawData").setParameter("ADDRESS_ID", address1.getID()).executeUpdate();
} catch (RuntimeException exception) {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
// Re-throw exception to ensure stacktrace appears in test result.
throw exception;
}
commitTransaction(em);
closeEntityManager(em);
}
/**
* Tests a @PrivateOwned @OneToMany mapping.
*/
public void testRemoveDepartmentWithPrivateOwnedEquipment() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
Department department = em.find(Department.class, deptId);
if (department == null) {
fail("Department with id="+deptId+", was not found.");
} else {
Collection<Equipment> equipment = department.getEquipment().values();
if (equipment.isEmpty()){
fail("Department with id="+deptId+", did not have any equipment.");
} else {
em.remove(department);
commitTransaction(em);
assertNull("Department itself was not removed.", em.find(Department.class, deptId));
for (Equipment e : equipment) {
assertNull("New equipment was not deleted.", em.find(Equipment.class, e.getId()));
}
}
}
} 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 testRelationshipReadDuringClone(){
EntityManager em = createEntityManager();
Session session = getServerSession();
ClassDescriptor departmentDesc = session.getDescriptor(Department.class);
DescriptorEventAdapter listener = new DescriptorEventAdapter(){
public void postClone(DescriptorEvent event) {
((Department)event.getObject()).getEquipment().size();
}
};
departmentDesc.getDescriptorEventManager().addListener(listener);
em.createQuery("SELECT e from Equipment e where e.department is not null").getResultList();
departmentDesc.getDescriptorEventManager().removeListener(listener);
departmentDesc.getDescriptorEventManager().initialize((AbstractSession) session);
closeEntityManager(em);
}
/**
* Tests trying to update a read only class.
*/
public void testUpdateReadOnlyEquipmentCode() {
EntityManager em = createEntityManager();
beginTransaction(em);
try {
Query query = em.createNamedQuery("findSQLEquipmentCodeA");
EquipmentCode equipmentCode = (EquipmentCode) query.getSingleResult();
equipmentCode.setCode("Z");
commitTransaction(em);
// Nothing should have been written to the database. Query for
// EquipmentCode A again. If an exception is caught, then it was
// not found, therefore, updated on the db.
try {
query = em.createNamedQuery("findSQLEquipmentCodeA");
query.getSingleResult();
} catch (Exception e) {
fail("The read only EquipmentA was modified");
}
} 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.setFirstName(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 {
employee = em.find(Employee.class, employee.getId());
em.remove(employee);
commitTransaction(em);
} finally {
if (isTransactionActive(em)){
rollbackTransaction(em);
}
closeEntityManager(em);
}
if(errorMsg.length() > 0) {
fail(errorMsg);
}
}
/**
* Tests Property and Properties annotations
*/
public void testProperty() {
EntityManager em = createEntityManager();
ClassDescriptor descriptor = getServerSession().getDescriptorForAlias("Employee");
ClassDescriptor aggregateDescriptor = getServerSession().getDescriptor(EmploymentPeriod.class);
closeEntityManager(em);
String errorMsg = "";
if (descriptor == null) {
errorMsg += " Descriptor for Employee 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, "Employee");
errorMsg += verifyPropertyValue(descriptor, "entityIntegerProperty", Integer.class, new Integer(1));
// 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, "byte[]Property", byte[].class, new byte[]{1, 2, 3, 4});
errorMsg += verifyPropertyValue(mapping, "char[]Property", char[].class, new char[]{'a', 'b', 'c'});
errorMsg += verifyPropertyValue(mapping, "Byte[]Property", Byte[].class, new byte[]{1, 2, 3, 4});
errorMsg += verifyPropertyValue(mapping, "Character[]Property", Character[].class, new char[]{'a', 'b', 'c'});
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"));
// verify property set on EmploymentPeriod embeddable
errorMsg += verifyPropertyValue(aggregateDescriptor, "embeddableClassName", String.class, "EmploymentPeriod");
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 Employee e WHERE e.lastName = '"+lastName+"'").getResultList();
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
ServerSession session = JUnitTestCase.getServerSession();
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 Employee e WHERE e.lastName = '"+lastName+"'").getResultList();
// 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
ServerSession session = JUnitTestCase.getServerSession();
beginTransaction(em);
String errorMsg = "";
try{
for(int i=0; i<employeesPersisted.size(); i++) {
for(int j=0; j<employeesRead.size(); j++) {
if (isOnServer()) {
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.";
}
}
} else {
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 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 Employee 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 Employee e JOIN FETCH e.dealers WHERE e.lastName = '"+lastName+"'").getResultList();
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));
}
}
ServerSession session = JUnitTestCase.getServerSession();
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); ";
}
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 Employee 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);
}
}
/**
* 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", getServerSession().compareObjects(violation, refreshedViolation));
} catch (Exception e) {
fail("An error occurred: " + e.getMessage());
} finally {
closeEntityManager(em);
}
}
/**
* Bug 470161 - ServerSession links RepeatableWriteUnitOfWork via entity / IndirectList / QueryBasedValueHolder\
*
* Through the UoW: Persist a new object, read an existing object in (building from rows, original not put in the
* shared cache), associate existing object with new object, commit. Previously, after the changes are merged
* into the shared cache, the transparent collection on the existing object has a wrapped VH from the initial uow
* query, which internally references the uow session, not the shared session.
*/
public void testTransparentIndirectionValueHolderSessionReset() {
Employee emp = null;
Dealer dealer = null;
// setup
EntityManager em = createEntityManager();
try {
beginTransaction(em);
dealer = new Dealer();
dealer.setFirstName("Angle");
dealer.setLastName("Bracket");
em.persist(dealer);
commitTransaction(em);
} finally {
closeEntityManager(em);
clearCache(); // start test with an empty cache
}
// test
em = createEntityManager();
try {
beginTransaction(em);
emp = new Employee();
emp.setFemale();
emp.setFirstName("Case");
emp.setLastName("Statement");
em.persist(emp);
Query query = em.createQuery("select d from Dealer d where d.firstName = :firstName and d.lastName = :lastName");
query.setParameter("firstName", dealer.getFirstName());
query.setParameter("lastName", dealer.getLastName());
List<Dealer> resultsList = query.getResultList();
assertTrue("List returned should be non-empty", resultsList.size() > 0);
Dealer dealerFound = resultsList.get(0);
emp.addDealer(dealerFound);
commitTransaction(em);
// verify valueholder configuration in shared cache
ServerSession parentSession = JpaHelper.getEntityManager(em).getServerSession();
Dealer cachedDealer = (Dealer) parentSession.getIdentityMapAccessor().getFromIdentityMap(dealer);
assertNotNull("Dealer with id should be in the cache: " + dealer.getId(), cachedDealer);
ClassDescriptor descriptor = parentSession.getDescriptor(Dealer.class);
DatabaseMapping mapping = descriptor.getMappingForAttributeName("customers");
IndirectCollection indirectCollection = (IndirectCollection) mapping.getAttributeValueFromObject(cachedDealer);
assertFalse("Collection VH should be uninstantiated", indirectCollection.isInstantiated());
DatabaseValueHolder dbValueHolder = (DatabaseValueHolder) indirectCollection.getValueHolder();
assertFalse("Referenced VH should be uninstantiated", dbValueHolder.isInstantiated());
Session vhSession = dbValueHolder.getSession();
assertSame("Dealer.customers VH session should reference the shared session", parentSession, vhSession);
} finally {
closeEntityManager(em);
}
// reset
em = createEntityManager();
try {
beginTransaction(em);
emp = em.find(Employee.class, emp.getId());
if (emp != null) {
em.remove(emp);
}
dealer = em.find(Dealer.class, dealer.getId());
if (dealer != null) {
em.remove(dealer);
}
commitTransaction(em);
} finally {
closeEntityManager(em);
}
}
/**
* Bug 474956 RepeatableUnitOfWork linked by Embeddable in shared cache in specific scenario
* Test the invalidation and refresh of a parent object with an Embeddable instantiated
* with non-null values. After associating the parent with another object, the Embeddable
* should not reference a UnitOfWork (via a change listener) within the shared cache.
*/
public void testInvalidateAndRefreshEmbeddableParent() {
// test depends on weaving
if (!isWeavingEnabled()) {
warning("Test depends on weaving and change tracking");
return;
}
HockeyPuck puck = null;
HockeyRink rink = null;
// setup
clearCache();
EntityManager em = createEntityManager();
try {
beginTransaction(em);
puck = new HockeyPuck();
puck.setId(1);
puck.setName("MrWraparound");
puck.getSponsor().setName("ACME Cloud Computing Company, Inc.");
puck.getSponsor().setSponsorshipValue(1000000);
em.persist(puck);
commitTransaction(em);
} finally {
closeEntityManager(em);
}
// test
em = createEntityManager();
try {
// 1. invalidate existing Entity in the cache
JpaHelper.getDatabaseSession(getEntityManagerFactory()).getIdentityMapAccessor().invalidateObject(puck.getId(), HockeyPuck.class);
assertFalse("Existing cached HockeyPuck should not be valid",
JpaHelper.getDatabaseSession(getEntityManagerFactory()).getIdentityMapAccessor().isValid(puck.getId(), HockeyPuck.class));
beginTransaction(em);
// 2. create new Entity and persist
rink = new HockeyRink();
rink.setId(1);
em.persist(rink);
// 3. load existing Entity
puck = em.createQuery("select object(p) from HockeyPuck p where p.id = " + puck.getId(), HockeyPuck.class).getSingleResult();
assertNotNull("HockeyPuck loaded should not be null", puck);
// 4. associate loaded existing Entity with persisted new Entity
rink.setPuck(puck);
commitTransaction(em);
} finally {
closeEntityManager(em);
}
// verify, go directly to the shared cache for the parent Entity
try {
HockeyPuck cachedPuck = (HockeyPuck)JpaHelper.getDatabaseSession(getEntityManagerFactory()).getIdentityMapAccessor().getFromIdentityMap(puck.getId(), HockeyPuck.class);
HockeySponsor sponsor = cachedPuck.getSponsor();
if (sponsor instanceof ChangeTracker) {
PropertyChangeListener listener = ((ChangeTracker)sponsor)._persistence_getPropertyChangeListener();
// listener can be null
if (listener != null && listener instanceof AttributeChangeListener) {
assertNull("UnitOfWork referenced in Embeddable referenced by an object in the shared cache", ((AttributeChangeListener)listener).getUnitOfWork());
}
} else {
fail("Config error: HockeyPuck/HockeySponsor is not change tracked");
}
} finally {
// reset
em = createEntityManager();
beginTransaction(em);
if (puck != null) {
puck = em.find(HockeyPuck.class, puck.getId());
if (puck != null) {
em.remove(puck);
}
}
if (rink != null) {
rink = em.find(HockeyRink.class, rink.getId());
if (rink != null) {
em.remove(rink);
}
}
commitTransaction(em);
closeEntityManager(em);
}
}
/**
* Bug 489898 - RepeatableWriteUnitOfWork linked by QueryBasedValueHolder in shared cache in specific scenario
*
* Complex scenario: In a transaction, associate an existing object to a new object, refresh the existing object.
* In a second transaction, read the new object and traverse relationships to the existing object, and trigger
* an indirect relationship. The existing wrapped indirection query on the indirect relationship should
* ensure that the UnitOfWork (RepeatableWriteUnitOfWork) used for the query is unreferenced correctly, to
* avoid referencing it within the shared cache, via the existing referenced query.
*/
public void testTransparentIndirectionQuerySessionReset() {
Bill bill = null;
BillLine billLine = null;
BillLineItem billLineItem = null;
BillAction billAction = null;
// setup
EntityManager em = createEntityManager();
try {
beginTransaction(em);
bill = new Bill();
bill.setOrderIdentifier("Test Bill");
billLine = new BillLine();
billLine.setQuantity(6);
bill.addBillLine(billLine);
billLineItem = new BillLineItem();
billLineItem.setItemName("Test Widget");
billLine.addBillLineItem(billLineItem);
em.persist(bill);
em.persist(billLine);
em.persist(billLineItem);
commitTransaction(em);
assertNotNull("bill should be non-null", bill);
assertNotNull("bill's id should be non-null", bill.getId());
assertNotNull("billLine should be non-null", billLine);
assertNotNull("billLine's id should be non-null", billLine.getId());
assertNotNull("billLineItem should be non-null", billLineItem);
assertNotNull("billLineItem's id should be non-null", billLineItem.getId());
} finally {
closeEntityManager(em);
clearCache(); // start test with an empty cache
}
try {
// test - txn #1 : read, modify, persist, refresh related Entity
em = createEntityManager();
try {
beginTransaction(em);
Bill billReRead = em.createQuery("SELECT b FROM Bill b where b.id=" + bill.getId(), Bill.class).getSingleResult();
assertNotNull(billReRead);
BillLine billLineReRead = billReRead.getBillLines().get(0);
assertNotNull(billLineReRead);
billAction = new BillAction();
billAction.setBillLine(billLineReRead);
billAction.setPriority(2);
em.persist(billAction);
em.refresh(billLineReRead); // refresh
commitTransaction(em);
} finally {
if (isTransactionActive(em)) {
rollbackTransaction(em);
}
closeEntityManager(em);
}
// test - txn #2 : read, modify and trigger relationship on related Entity
em = createEntityManager();
try {
beginTransaction(em);
Bill billReRead = em.createQuery("SELECT b FROM Bill b where b.id=" + bill.getId(), Bill.class).getSingleResult();
billReRead.setStatus(Bill.STATUS_PROCESSING); // DM: if there is no update to Order, issue doesn't occur
BillAction billActionReRead = em.createQuery("SELECT a FROM BillAction a where a.id=" + billAction.getId(), BillAction.class).getSingleResult();
assertNotNull(billActionReRead);
BillLine billLineReRead = billActionReRead.getBillLine();
assertNotNull(billLineReRead);
billLineReRead.getBillLineItems().size(); // Access & trigger BillLine -> BillLineItems list
commitTransaction(em);
} finally {
if (isTransactionActive(em)) {
rollbackTransaction(em);
}
closeEntityManager(em);
}
// verify
// Failure case: non-null session (a UnitOfWork/RepeatableWriteUnitOfWork) referenced in the wrapped ValueHolder's query.
ServerSession srv = getServerSession();
ClassDescriptor descriptor = srv.getDescriptor(billLine);
Long blId = billLine.getId();
BillLine cachedBillLine = (BillLine)srv.getIdentityMapAccessor().getFromIdentityMap(blId, BillLine.class);
assertNotNull("BillLine from shared cache is null with id: " + blId, cachedBillLine);
OneToManyMapping mapping = (OneToManyMapping)srv.getDescriptor(cachedBillLine).getMappingForAttributeName("billLineItems");
IndirectContainer billLineItemsVH = (IndirectContainer) mapping.getAttributeValueFromObject(cachedBillLine);
assertNotNull("BillLineItems ValueHolder should not be null", billLineItemsVH);
ValueHolderInterface wrappedVH = billLineItemsVH.getValueHolder();
assertNotNull("Wrapped ValueHolder should not be null", wrappedVH);
if (wrappedVH instanceof QueryBasedValueHolder) {
DatabaseQuery query = ((QueryBasedValueHolder)wrappedVH).getQuery();
if (query.getSession() != null && query.getSession().isUnitOfWork()) {
fail("UnitOfWork referenced in Query from wrapped QueryBasedValueHolder in shared cache");
}
}
} finally {
// reset
em = createEntityManager();
try {
beginTransaction(em);
bill = em.find(Bill.class, bill.getId());
if (bill != null) {
em.remove(bill);
}
billLine = em.find(BillLine.class, billLine.getId());
if (billLine != null) {
em.remove(billLine);
}
billLineItem = em.find(BillLineItem.class, billLineItem.getId());
if (billLineItem != null) {
em.remove(billLineItem);
}
if (billAction != null) {
billAction = em.find(BillAction.class, billAction.getId());
if (billAction != null) {
em.remove(billAction);
}
}
commitTransaction(em);
} finally {
closeEntityManager(em);
}
}
}
protected int getVersion(EntityManager em, Dealer dealer) {
Vector pk = new Vector(1);
pk.add(dealer.getId());
return ((Integer)getServerSession().getDescriptor(Dealer.class).getOptimisticLockingPolicy().getWriteLockValue(dealer, pk, getServerSession())).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.setFirstName(Integer.toString(i+1));
emp.setLastName(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 AdvancedCustomer c WHERE c.lastName = '"+lastName+"'").executeUpdate();
em.createQuery("DELETE FROM Dealer d WHERE d.lastName = '"+lastName+"'").executeUpdate();
Query q = em.createQuery("SELECT e FROM Employee 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();
}
}
}