From 357cf347c8162ccc680861ab17934eb1dfa1a353 Mon Sep 17 00:00:00 2001 From: Fay Wang Date: Thu, 19 Feb 2009 00:30:06 +0000 Subject: [PATCH] OPENJPA-871: mappedById support git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@745699 13f79535-47bb-0310-9956-ffa450edef68 --- .../jdbc/kernel/AbstractUpdateManager.java | 53 ++++++++- .../jdbc/kernel/ConstraintUpdateManager.java | 4 +- .../kernel/PreparedStatementManagerImpl.java | 3 +- .../openjpa/jdbc/meta/FieldMapping.java | 89 ++++++++++++--- .../meta/strats/RelationFieldStrategy.java | 14 ++- .../org/apache/openjpa/jdbc/sql/RowImpl.java | 9 ++ .../openjpa/kernel/StateManagerImpl.java | 21 ++-- .../apache/openjpa/meta/FieldMetaData.java | 4 + .../apache/openjpa/util/ApplicationIds.java | 75 ++++++++++++- .../enhance/identity/MedicalHistory2.java | 81 ++++++++++++++ .../persistence/enhance/identity/Person2.java | 80 +++++++++++++ .../enhance/identity/TestMappedById.java | 105 +++++++++++++++++- 12 files changed, 503 insertions(+), 35 deletions(-) create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/MedicalHistory2.java create mode 100644 openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Person2.java diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java index e2a7ffaeb..54262f13f 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/AbstractUpdateManager.java @@ -20,10 +20,12 @@ package org.apache.openjpa.jdbc.kernel; import java.sql.Connection; import java.sql.SQLException; +import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.Iterator; import java.util.LinkedList; +import java.util.List; import org.apache.openjpa.jdbc.conf.JDBCConfiguration; import org.apache.openjpa.jdbc.meta.ClassMapping; @@ -36,8 +38,10 @@ import org.apache.openjpa.jdbc.sql.RowManager; import org.apache.openjpa.jdbc.sql.SQLExceptions; import org.apache.openjpa.kernel.OpenJPAStateManager; import org.apache.openjpa.kernel.PCState; +import org.apache.openjpa.kernel.StateManagerImpl; import org.apache.openjpa.lib.conf.Configurable; import org.apache.openjpa.lib.conf.Configuration; +import org.apache.openjpa.meta.ClassMetaData; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.OpenJPAException; import org.apache.openjpa.util.OptimisticException; @@ -81,12 +85,29 @@ public abstract class AbstractUpdateManager RowManager rowMgr = newRowManager(); Collection customs = new LinkedList(); Collection exceps = psMgr.getExceptions(); - for (Iterator itr = states.iterator(); itr.hasNext();) - exceps = populateRowManager((OpenJPAStateManager) itr.next(), - rowMgr, store, exceps, customs); + Collection mappedByIdStates = new ArrayList(); + for (Iterator itr = states.iterator(); itr.hasNext();) { + OpenJPAStateManager obj = (OpenJPAStateManager)itr.next(); + if (obj instanceof StateManagerImpl) { + StateManagerImpl sm = (StateManagerImpl) obj; + if (sm.getMappedByIdFields() != null) + mappedByIdStates.add(sm); + else exceps = populateRowManager(sm, rowMgr, store, exceps, customs); + } else + exceps = populateRowManager(obj, rowMgr, store, exceps, customs); + } // flush rows exceps = flush(rowMgr, psMgr, exceps); + + if (mappedByIdStates.size() != 0) { + for (Iterator itr = mappedByIdStates.iterator(); itr.hasNext();) { + StateManagerImpl sm = (StateManagerImpl) itr.next(); + exceps = populateRowManager(sm, rowMgr, store, exceps, customs); + } + // flush rows + exceps = flush(rowMgr, psMgr, exceps); + } // now do any custom mappings for (Iterator itr = customs.iterator(); itr.hasNext();) { @@ -190,6 +211,16 @@ public abstract class AbstractUpdateManager mapping.insert(sm, store, rowMgr); FieldMapping[] fields = mapping.getDefinedFieldMappings(); + if (((StateManagerImpl)sm).getMappedByIdFields() != null) { + // when there is mappedByIdFields, the id field is not + // fully populated. We need to insert other fields first + // so that in the process of inserting other fields, + // the values of mappedById fields can be set into + // the id fields. Once the id fields are fully populated, + // we will then insert the id fields. + fields = reorderFields(fields); + } + BitSet dirty = sm.getDirty(); for (int i = 0; i < fields.length; i++) { if (dirty.get(fields[i].getIndex()) @@ -206,6 +237,22 @@ public abstract class AbstractUpdateManager dsc.insert(sm, store, rowMgr); } } + + private FieldMapping[] reorderFields(FieldMapping[] fields) { + List pkFmds = new ArrayList(); + FieldMapping[] ret = new FieldMapping[fields.length]; + int j = 0; + for (int i = 0; i < fields.length; i++) { + if (!fields[i].isPrimaryKey()) + ret[j++] = fields[i]; + else + pkFmds.add(fields[i]); + } + for (int i = 0; i 0) { + //The name of the attribute within the composite key to which + //the relationship attribute corresponds. + Object target = ((ObjectId)sm.getObjectId()).getId(); + setMappedByIdValue(target, pkVal, mappedByIdFieldName); + pkVal = target; + } + sm.storeObjectField(fmds[0].getIndex(), pkVal); + } + } + + public void setMappedByIdValue(Object target, + Object val, String mappedByIdFieldName) { + Reflection.set(target, + Reflection.findField(target.getClass(), mappedByIdFieldName, true), + val); + } + public void update(OpenJPAStateManager sm, JDBCStore store, RowManager rm) throws SQLException { assertStrategy().update(sm, store, rm); diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java index b1fdddd34..42bffc09d 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/strats/RelationFieldStrategy.java @@ -54,6 +54,7 @@ import org.apache.openjpa.jdbc.sql.Select; import org.apache.openjpa.jdbc.sql.SelectExecutor; import org.apache.openjpa.jdbc.sql.Union; import org.apache.openjpa.kernel.OpenJPAStateManager; +import org.apache.openjpa.kernel.StateManagerImpl; import org.apache.openjpa.lib.log.Log; import org.apache.openjpa.lib.util.Localizer; import org.apache.openjpa.meta.ClassMetaData; @@ -213,14 +214,21 @@ public class RelationFieldStrategy mappedByIdValue.length() == 0) { if (fmds[i].getValue().getEmbeddedMetaData() != null) { EmbedValueHandler.getEmbeddedIdCols((FieldMapping)fmds[i], cols); - } else { + } else EmbedValueHandler.getIdColumns((FieldMapping)fmds[i], cols); } } - } + return cols; + } else { // primary key is single-value + Class pkType = pk.getDeclaredType(); + FieldMetaData[] pks = field.getValue().getDeclaredTypeMetaData().getPrimaryKeyFields(); + if (pks.length != 1 || pks[0].getDeclaredType() != pkType) + return Collections.EMPTY_LIST; + pkCols = pk.getColumns(); + for (int i = 0; i < pkCols.length; i++) + cols.add(pkCols[i]); return cols; } - return Collections.EMPTY_LIST; } /** diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowImpl.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowImpl.java index b59a47c53..d54ab68f4 100644 --- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowImpl.java +++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/RowImpl.java @@ -68,6 +68,7 @@ public class RowImpl private final int[] _types; private String _sql = null; + private boolean _isFlushed = false; /** * Constructor. @@ -960,4 +961,12 @@ public class RowImpl public int[] getTypes() { return _types; } + + public boolean isFlushed() { + return _isFlushed; + } + + public void setFlushed(boolean isFlushed) { + _isFlushed = isFlushed; + } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java index ec7d5a4cd..b4f8d0f8a 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java @@ -33,6 +33,7 @@ import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.TimeZone; import java.util.concurrent.locks.ReentrantLock; @@ -60,7 +61,6 @@ import org.apache.openjpa.util.Exceptions; import org.apache.openjpa.util.ImplHelper; import org.apache.openjpa.util.InternalException; import org.apache.openjpa.util.InvalidStateException; -import org.apache.openjpa.util.ObjectId; import org.apache.openjpa.util.ObjectNotFoundException; import org.apache.openjpa.util.OpenJPAId; import org.apache.openjpa.util.ProxyManager; @@ -149,7 +149,7 @@ public class StateManagerImpl // information about the owner of this instance, if it is embedded private StateManagerImpl _owner = null; private int _ownerIndex = -1; - private int _mappedByIdValueFrom = -1; + private List _mappedByIdFields = null; private transient ReentrantLock _instanceLock = null; @@ -304,10 +304,15 @@ public class StateManagerImpl || fmds[i].getManagement() != fmds[i].MANAGE_PERSISTENT) _loaded.set(i); - if (_meta.getIdentityType() == ClassMetaData.ID_APPLICATION && - fmds[i].getMappedByIdValue() != null && - ((ObjectId)_id).getId() == null) { - _mappedByIdValueFrom = fmds[i].getIndex(); + if (_meta.getIdentityType() == ClassMetaData.ID_APPLICATION) { + String mappedByIdValue = fmds[i].getMappedByIdValue(); + if (mappedByIdValue != null) { + if (!ApplicationIds.isIdSet(_id, _meta, mappedByIdValue)) { + if (_mappedByIdFields == null) + _mappedByIdFields = new ArrayList(); + _mappedByIdFields.add(fmds[i]); + } + } } // record whether there are any managed inverse fields if (_broker.getInverseManager() != null @@ -3280,7 +3285,7 @@ public class StateManagerImpl return pc; } - public int getMappedByIdValueFrom() { - return _mappedByIdValueFrom; + public List getMappedByIdFields() { + return _mappedByIdFields; } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java index 7d649b709..3d723df9d 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/meta/FieldMetaData.java @@ -2164,4 +2164,8 @@ public class FieldMetaData public void setMappedByIdValue(String mappedByIdValue) { this._mappedByIdValue = mappedByIdValue; } + + public boolean isMappedById() { + return (_mappedByIdValue != null); + } } diff --git a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java index 84022384d..ea3a2e8bf 100644 --- a/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java +++ b/openjpa-kernel/src/main/java/org/apache/openjpa/util/ApplicationIds.java @@ -491,9 +491,80 @@ public class ApplicationIds { } return true; } + + /** + * Check if object id is set or not. + */ + public static boolean isIdSet(Object id, ClassMetaData meta, + String mappedByIdFieldName) { + Object key = null; + if (meta.isOpenJPAIdentity()) + key = ApplicationIds.getKey(id, meta); + else + key = ((ObjectId)id).getId(); + Object val = null; + if (mappedByIdFieldName.length() != 0) { + Class idClass = ((ObjectId)id).getId().getClass(); + val = Reflection.get(key, + Reflection.findField(idClass, mappedByIdFieldName, true)); + } else + val = key; + + boolean notSet = (val == null + || (val instanceof String && ((String)val).length() == 0) + || (val instanceof Number && ((Number)val).longValue() == 0)); + return !notSet; + } - public static void setKey(ObjectId fromId, ObjectId toId) { - toId.setId(fromId.getId()); + /** + * Return the key from the given id. + */ + public static Object getKey(Object id, ClassMetaData meta) { + if (meta == null || id == null) + return null; + + if (meta.isOpenJPAIdentity()) { + int type = meta.getPrimaryKeyFields()[0].getObjectIdFieldTypeCode(); + switch (type) { + case JavaTypes.BYTE: + case JavaTypes.BYTE_OBJ: + return ((ByteId)id).getId(); + case JavaTypes.CHAR: + case JavaTypes.CHAR_OBJ: + return ((CharId)id).getId(); + case JavaTypes.DOUBLE: + case JavaTypes.DOUBLE_OBJ: + return ((DoubleId)id).getId(); + case JavaTypes.FLOAT: + case JavaTypes.FLOAT_OBJ: + return ((FloatId)id).getId(); + case JavaTypes.INT: + case JavaTypes.INT_OBJ: + return ((IntId)id).getId(); + case JavaTypes.LONG: + case JavaTypes.LONG_OBJ: + return ((LongId)id).getId(); + case JavaTypes.SHORT: + case JavaTypes.SHORT_OBJ: + return ((ShortId)id).getId(); + case JavaTypes.STRING: + return ((StringId)id).getId(); + case JavaTypes.DATE: + return ((DateId)id).getId(); + case JavaTypes.OID: + case JavaTypes.OBJECT: + return ((ObjectId)id).getId(); + case JavaTypes.BIGDECIMAL: + return ((BigDecimalId)id).getId(); + case JavaTypes.BIGINTEGER: + return ((BigIntegerId)id).getId(); + default: + throw new InternalException(); + } + } else { // IdClass + return ((ObjectId)id).getId(); + } + } /** diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/MedicalHistory2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/MedicalHistory2.java new file mode 100644 index 000000000..d457d3461 --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/MedicalHistory2.java @@ -0,0 +1,81 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.enhance.identity; + +import javax.persistence.*; + +@Entity +public class MedicalHistory2 { + @Id + long id; + + String name; + + @MappedById + @OneToOne Person2 patient; + + public Person2 getPatient() { + return patient; + } + + public void setPatient(Person2 p) { + this.patient = p; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public boolean equals(Object o) { + if (o == null) return false; + if (!(o instanceof MedicalHistory2)) return false; + MedicalHistory2 m0 = (MedicalHistory2)o; + String name0 = m0.getName(); + if (name != null && !name.equals(name0)) return false; + if (name == null && name0 != null) return false; + long id0 = m0.getId(); + if (id != id0) return false; + Person2 p0 = m0.getPatient(); + if (patient != null && p0 != null && patient.ssn != p0.ssn) return false; + if (patient == null && p0 != null) return false; + if (patient != null && p0 == null) return false; + return true; + } + + public int hashCode() { + int ret = 0; + ret = ret * 31 + name.hashCode(); + ret = ret * 31 + (int) id; + ret = ret * 31 + (int) patient.ssn; + return ret; + } + +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Person2.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Person2.java new file mode 100644 index 000000000..ea2d7392c --- /dev/null +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/Person2.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.openjpa.persistence.enhance.identity; + +import javax.persistence.*; + +@Entity +public class Person2 { + @Id + @GeneratedValue(strategy=GenerationType.IDENTITY) + long ssn; + + @OneToOne(mappedBy="patient") + MedicalHistory2 medical; + + String name; + + public long getSsn() { + return ssn; + } + + public void setSsn(long ssn) { + this.ssn = ssn; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public MedicalHistory2 getMedical() { + return medical; + } + + public void setMedical(MedicalHistory2 medical) { + this.medical = medical; + } + + public boolean equals(Object o) { + if (o == null) return false; + if (!(o instanceof Person2)) return false; + Person2 p0 = (Person2)o; + long ssn0 = p0.getSsn(); + String name0 = p0.getName(); + MedicalHistory2 medical0 = p0.getMedical(); + if (ssn != ssn0) return false; + if (name != name0) return false; + if (medical != null && medical0 != null && medical.id != medical0.id) return false; + if (medical == null && medical0 != null) return false; + if (medical != null && medical0 == null) return false; + return true; + } + + public int hashCode() { + int ret = 0; + ret = ret * 31 + (int) ssn; + if (medical != null) + ret = ret * 31 + medical.hashCode(); + return ret; + } +} diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/TestMappedById.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/TestMappedById.java index 407a7b5d6..e40a0802c 100644 --- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/TestMappedById.java +++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/enhance/identity/TestMappedById.java @@ -26,6 +26,8 @@ import javax.persistence.EntityManager; import javax.persistence.EntityTransaction; import javax.persistence.Query; +import junit.framework.Assert; + import org.apache.openjpa.persistence.test.SingleEMFTestCase; public class TestMappedById extends SingleEMFTestCase { @@ -40,6 +42,9 @@ public class TestMappedById extends SingleEMFTestCase { public Map persons1 = new HashMap(); public Map medicals1 = new HashMap(); + public Map persons2 = new HashMap(); + public Map medicals2 = + new HashMap(); public int eId1 = 1; public int dId1 = 1; @@ -47,12 +52,15 @@ public class TestMappedById extends SingleEMFTestCase { public int dId2 = 1; public int pId1 = 1; public int mId1 = 1; + public int pId2 = 1; + public int mId2 = 1; public void setUp() throws Exception { super.setUp(DROP_TABLES, Dependent1.class, Employee1.class, DependentId1.class, Dependent2.class, Employee2.class, DependentId2.class, EmployeeId2.class, MedicalHistory1.class, - Person1.class, PersonId1.class); + Person1.class, PersonId1.class, MedicalHistory2.class, + Person2.class); } /** @@ -82,6 +90,14 @@ public class TestMappedById extends SingleEMFTestCase { queryObj3(); } + /** + * This is spec 2.4.1.2 Example 4, case(b) with generated key + */ + public void testMappedById4() { + createObj4(); + queryObj4(); + } + public void createObj1() { EntityManager em = emf.createEntityManager(); EntityTransaction tran = em.getTransaction(); @@ -282,22 +298,103 @@ public class TestMappedById extends SingleEMFTestCase { Query q = em.createQuery(jpql); List ms = q.getResultList(); for (MedicalHistory1 m : ms) { - assertMedicalHistory(m, firstName); + assertMedicalHistory1(m, firstName); } jpql = "select m from MedicalHistory1 m where m.id.firstName = '" + firstName + "'"; q = em.createQuery(jpql); ms = q.getResultList(); for (MedicalHistory1 m : ms) { - assertMedicalHistory(m, firstName); + assertMedicalHistory1(m, firstName); } tran.commit(); em.close(); } - public void assertMedicalHistory(MedicalHistory1 m, String firstName) { + public void assertMedicalHistory1(MedicalHistory1 m, String firstName) { MedicalHistory1 m0 = medicals1.get(firstName); assertEquals(m0, m); } + + public void createObj4() { + EntityManager em = emf.createEntityManager(); + EntityTransaction tran = em.getTransaction(); + for (int i = 0; i < numPersons; i++) + createPerson2(em, pId2++); + tran.begin(); + em.flush(); + tran.commit(); + em.close(); + } + + public Person2 createPerson2(EntityManager em, int id) { + Person2 p = new Person2(); + p.setName("p_" + id); + + MedicalHistory2 m = createMedicalHistory2(em, mId2++); + m.setPatient(p); // automatically set the id + p.setMedical(m); + em.persist(m); + medicals2.put(m.getName(), m); + + em.persist(p); + persons2.put(p.getName(), p); + return p; + } + + public MedicalHistory2 createMedicalHistory2(EntityManager em, int id) { + MedicalHistory2 m = new MedicalHistory2(); + m.setName("medical_" + id); + return m; + } + + public void findObj4(long ssn) { + EntityManager em = emf.createEntityManager(); + Person2 p = em.find(Person2.class, ssn); + Person2 p1 = p.getMedical().getPatient(); + Assert.assertEquals(p1, p); + } + + public void queryObj4() { + queryMedicalHistory4(); + } + + public void queryMedicalHistory4() { + EntityManager em = emf.createEntityManager(); + Map medicals = new HashMap(); + long ssn = 0; + EntityTransaction tran = em.getTransaction(); + tran.begin(); + String jpql = "select m from MedicalHistory2 m"; + Query q = em.createQuery(jpql); + List ms = q.getResultList(); + for (MedicalHistory2 m : ms) { + ssn = m.getId(); + } + tran.commit(); + em.close(); + + em = emf.createEntityManager(); + tran = em.getTransaction(); + tran.begin(); + jpql = "select m from MedicalHistory2 m where m.patient.ssn = " + ssn; + q = em.createQuery(jpql); + ms = q.getResultList(); + for (MedicalHistory2 m : ms) { + assertMedicalHistory2(m); + } + tran.commit(); + em.close(); + + findObj4(ssn); + } + + public void assertMedicalHistory2(MedicalHistory2 m) { + String name = m.getName(); + MedicalHistory2 m0 = medicals2.get(name); + MedicalHistory2 m1 = m.getPatient().getMedical(); + Assert.assertEquals(m1, m); + } + }