mirror of https://github.com/apache/openjpa.git
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:
parent
1a4223d35b
commit
357cf347c8
|
@ -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,13 +85,30 @@ 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();) {
|
||||
try {
|
||||
|
@ -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())
|
||||
|
@ -207,6 +238,22 @@ public abstract class AbstractUpdateManager
|
|||
}
|
||||
}
|
||||
|
||||
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
|
||||
* {@link CustomMapping} struct for it in the given collection and
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2164,4 +2164,8 @@ public class FieldMetaData
|
|||
public void setMappedByIdValue(String mappedByIdValue) {
|
||||
this._mappedByIdValue = mappedByIdValue;
|
||||
}
|
||||
|
||||
public boolean isMappedById() {
|
||||
return (_mappedByIdValue != null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -492,8 +492,79 @@ public class ApplicationIds {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static void setKey(ObjectId fromId, ObjectId toId) {
|
||||
toId.setId(fromId.getId());
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue