OPENJPA-871: mappedById support

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@745699 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Fay Wang 2009-02-19 00:30:06 +00:00
parent 1a4223d35b
commit 357cf347c8
12 changed files with 503 additions and 35 deletions

View File

@ -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<FieldMapping> pkFmds = new ArrayList<FieldMapping>();
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 <pkFmds.size(); i++) {
ret[j++] = pkFmds.get(i);
}
return ret;
}
/**
* If the given mapping uses a custom insert, places a

View File

@ -545,8 +545,10 @@ public class ConstraintUpdateManager
RowImpl row;
for (Iterator itr = rows.iterator(); itr.hasNext(); ) {
row = (RowImpl) itr.next();
if (row.isValid() && !row.isDependent())
if (!row.isFlushed() && row.isValid() && !row.isDependent()) {
psMgr.flush(row);
row.setFlushed(true);
}
}
}
}

View File

@ -78,7 +78,8 @@ public class PreparedStatementManagerImpl
public void flush(RowImpl row) {
try {
flushInternal(row);
if (!row.isFlushed())
flushInternal(row);
} catch (SQLException se) {
_exceptions.add(SQLExceptions.getStore(se, _dict));
} catch (OpenJPAException ke) {

View File

@ -19,11 +19,15 @@
package org.apache.openjpa.jdbc.meta;
import java.sql.SQLException;
import java.util.List;
import org.apache.openjpa.enhance.PersistenceCapable;
import org.apache.openjpa.enhance.Reflection;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
import org.apache.openjpa.jdbc.meta.strats.HandlerFieldStrategy;
import org.apache.openjpa.jdbc.meta.strats.NoneFieldStrategy;
import org.apache.openjpa.jdbc.meta.strats.PrimitiveFieldStrategy;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.ColumnIO;
import org.apache.openjpa.jdbc.schema.ForeignKey;
@ -42,12 +46,14 @@ 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;
import org.apache.openjpa.meta.FieldMetaData;
import org.apache.openjpa.meta.JavaTypes;
import org.apache.openjpa.util.ApplicationIds;
import org.apache.openjpa.util.InternalException;
import org.apache.openjpa.util.MetaDataException;
import org.apache.openjpa.util.ObjectId;
import org.apache.openjpa.util.OpenJPAId;
/**
* Specialization of metadata for relational databases.
@ -591,22 +597,79 @@ public class FieldMapping
public void insert(OpenJPAStateManager sm, JDBCStore store, RowManager rm)
throws SQLException {
if (sm instanceof StateManagerImpl) {
int mappedByIdValueFrom = ((StateManagerImpl)sm).getMappedByIdValueFrom();
if (isPrimaryKey() && mappedByIdValueFrom != -1) {
PersistenceCapable pc = (PersistenceCapable)sm.fetchObject(mappedByIdValueFrom);
StateManagerImpl pkSm = (StateManagerImpl)pc.pcGetStateManager();
ObjectId fromId = (ObjectId)pkSm.getId();
sm.storeObject(getIndex(), fromId.getId());
ObjectId toId = (ObjectId)sm.getId();
ApplicationIds.setKey(fromId, toId);
ObjectId toObjectId = (ObjectId)sm.getObjectId();
ApplicationIds.setKey(fromId, toObjectId);
}
}
setPKValueFromMappedByIdField(sm);
assertStrategy().insert(sm, store, rm);
}
private void setPKValueFromMappedByIdField(OpenJPAStateManager sm) {
if (sm instanceof StateManagerImpl) {
List mappedByIdFields = ((StateManagerImpl)sm).
getMappedByIdFields();
if (mappedByIdFields == null)
return;
if (!mappedByIdFields.contains(this))
return;
if (!isMappedById())
return;
PersistenceCapable pc = (PersistenceCapable)sm.
fetchObject(getIndex());
if (pc == null)
return;
StateManagerImpl pkSm = (StateManagerImpl)pc.
pcGetStateManager();
Object pkVal = getPKValue(pkSm);
if (pkVal == null)
return;
setPKValue((StateManagerImpl)sm, pkVal);
sm.setObjectId(
ApplicationIds.create(sm.getPersistenceCapable(),
sm.getMetaData()));
}
}
private Object getPKValue(StateManagerImpl pkSm) {
ClassMetaData pkMeta = pkSm.getMetaData();
FieldMetaData[] fmds = pkMeta.getPrimaryKeyFields();
// MappedById is for single value primary key or embeddable id
if (fmds.length == 0)
return null;
else
return ApplicationIds.getKey(pkSm.getObjectId(), pkMeta);
}
private void setPKValue(StateManagerImpl sm, Object pkVal) {
ClassMetaData meta = sm.getMetaData();
FieldMetaData[] fmds = meta.getPrimaryKeyFields();
if (fmds.length == 0)
return;
Strategy strat = ((FieldMapping)fmds[0]).getStrategy();
// single value primary key
if (strat instanceof PrimitiveFieldStrategy)
((PrimitiveFieldStrategy)strat).setAutoAssignedValue(sm, null, null,
pkVal);
else {
//composite key
String mappedByIdFieldName = getMappedByIdValue();
if (mappedByIdFieldName != null &&
mappedByIdFieldName.length() > 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);

View File

@ -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;
}
/**

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -2164,4 +2164,8 @@ public class FieldMetaData
public void setMappedByIdValue(String mappedByIdValue) {
this._mappedByIdValue = mappedByIdValue;
}
public boolean isMappedById() {
return (_mappedByIdValue != null);
}
}

View File

@ -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();
}
}
/**

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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<String, Person1> persons1 = new HashMap<String, Person1>();
public Map<String, MedicalHistory1> medicals1 =
new HashMap<String, MedicalHistory1>();
public Map<String, Person2> persons2 = new HashMap<String, Person2>();
public Map<String, MedicalHistory2> medicals2 =
new HashMap<String, MedicalHistory2>();
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<MedicalHistory1> 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<MedicalHistory2> 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);
}
}