[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[eclipselink-users] i encountere a Null primary key in some unit of work clone
|
Hi all
i'm using eclipselink 1.0.2 and i have some problem using custom insert mechanism. Here is my model
@MappedSuperclass
public abstract class DomainObject implements Serializable {
/**
*
*/
private static final long serialVersionUID = 8169331770517578695L;
public static final String PROP_ID = "id";
@Id
@ReturnInsert
protected Integer id;
public Integer getId() {
return id;
}
public void setId(Integer l) {
this.id = l;
}
@Override
public int hashCode() {
... generated from eclipse....
}
@Override
public boolean equals(Object obj) {
... generated from eclipse....
}
}
@Entity
@Table(name = "TOPCARE.PAT_VIEW")
@AttributeOverrides(value = { @AttributeOverride(name = "id", column = @Column(name = "PATIENT_ID")) })
public class Patient extends DomainObject {
@OneToMany(mappedBy = "patient", cascade = { MERGE, REFRESH }, fetch = LAZY)
@OrderBy("measurementDate DESC")
private List<Measurement> measurements = new Vector<Measurement>();
...
public void addMeasurement(Measurement measurement) {
if (measurement != null && !measurements.contains(measurement)) {
measurements.add(0, measurement);
measurement.setPatient(this);
}
}
.....
}
@MappedSuperclass
public abstract class AbstractMeasurement extends DomainObject {
...
@ManyToOne(cascade = { MERGE, REFRESH })
@JoinColumn(name = "PAT_PATIENT_ID", referencedColumnName = "PATIENT_ID")
private Patient patient;
@OneToOne(cascade = { PERSIST, MERGE, REFRESH })
@JoinColumn(name = "WORK_FLOW_ID", referencedColumnName = "WORKFLOW_ID")
protected Workflow workflow;
public AbstractMeasurement() {
init();
}
public AbstractMeasurement(Patient patient, Workflow workflow) {
setPatient(patient);
if (workflow == null)
workflow = new Workflow(patient);
this.workflow = workflow;
init();
}
private void init() {
// values = new HashMap<Object, AbstractMeasurementValue>();
if (patient == null)
patient = new Patient();
if (workflow == null)
workflow = new Workflow();
if (measurementDate == null)
measurementDate = new Date();
}
....
public Patient getPatient() {
return patient;
}
public void setPatient(Patient patient) {
if (patient != null && !patient.equals(this.patient)) {
this.patient = patient;
this.patient.addMeasurement(this);
}
}
@Entity
@Table(name = "TOPCARE.MEASUREMENT_VIEW")
@AttributeOverrides( {
@AttributeOverride(name = "measurementDate", column = @Column(name = "TIMEDATE")),
@AttributeOverride(name = "id", column = @Column(name = "MEASUREMENT_ID")) })
public class Measurement extends AbstractMeasurement {
....
/**
*
*/
public Measurement() {
init();
}
public Measurement(String kind, Patient patient) {
super(patient, new Workflow(patient));
System.out.println("patientID: " + patient.getId());
setKind(kind);
workflow.setKind(kind);
init();
}
private void init() {
values = new HashMap<String, AbstractMeasurementValue>();
}
}
@Entity
@Table(name = "TOPCARE.WORKFLOW_VIEW")
@AttributeOverride(name = "id", column = @Column(name = "WORKFLOW_ID"))
public class Workflow extends DomainObject {
....
@OneToOne
@JoinColumn(name = "PATIENT_ID", referencedColumnName = "PATIENT_ID")
private Patient patient;
/**
* INTERNAL!!!
*/
public Workflow() {
}
public Workflow(Patient patient) {
super();
this.patient = patient;
creationDate = new Date();
}
}
Since the application may only write in the database through stored procedures and stored functions, and read the data on views. That's why i customized all involved DomainTypes by implementing the interface
org.eclipse.persistence.config.DescriptorCustomizer. Here is the customize-method for type Measurement
public void customize(ClassDescriptor descriptor) throws Exception {
if (MeasurementValue.class.equals(descriptor.getJavaClass())) {
descriptor.setReadOnly();
return;
}
descriptor.setDefaultInsertObjectQueryRedirector(new QueryRedirector() {
/**
*
*/
private static final long serialVersionUID = 1L;
@SuppressWarnings("unchecked")
public Object invokeQuery(DatabaseQuery query, Record arguments,
Session session) {
Measurement measurement = (Measurement) ((InsertObjectQuery) query)
.getObject();
String measurementDateAsString = DateUtils
.changeDateTimeToDBFormat(measurement
.getMeasurementDate());
StoredProcedureCall storedProcedureCall = null;
Integer result = 0;
Vector<Object> parameters = null;
storedProcedureCall = new StoredProcedureCall();
storedProcedureCall
.setProcedureName("topcare.top_treatment.spo2_measurement_write");
storedProcedureCall.addNamedOutputArgument(
"p_recordcard_id", "MEASUREMENT_ID", Integer.class);
storedProcedureCall.addNamedArgument("p_patient_id");
storedProcedureCall.addNamedArgument("p_patient_id");
storedProcedureCall.addNamedArgument("p_measurement_date");
storedProcedureCall.addNamedArgument("p_SpO2");
storedProcedureCall.addNamedArgument("p_Pulse");
storedProcedureCall.addNamedArgument("p_work_flow_id");
parameters = new Vector<Object>();
parameters.add(0, storedProcedureCall.getParameters()
.get(0));
parameters.add(1, measurement.getPatient().getId());
parameters.add(2, measurementDateAsString);
parameters.add(3, measurement
.getValue(MeasurementValueKind.BODYSPO2));
parameters.add(4, measurement
.getValue(MeasurementValueKind.BODYPULSE2));
parameters.add(5, measurement.getWorkflow().getId());
logger.info("result: " + result);
storedProcedureCall.setParameters(parameters);
result = (Integer) ((DatabaseRecord) session
.executeSelectingCall(storedProcedureCall).get(0))
.get("MEASUREMENT_ID");
measurement.setId(result); // line 754
logger.info("generated measurementId:" + result); // line 755
return result; }
});
}
After saving the measurement using i printed out the generated id via a logger (see line 755) and i see this id. Since i set the id by calling setId(see line 754). I don't understand why i get the following exception on the second attempt to save. That means the first save call function properly since i find the data in the database, but the second doesn't.
[EL Warning]: 2008.12.10 09:10:02.296--UnitOfWork(5651650)--Thread(Thread[http-8080-Processor25,5,main])--Exception [EclipseLink-7197] (Eclipse Persistence Services - 1.0.2 (Build 20081024)): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null primary key encountered in unit of work clone [topcare.domain.patient.measurement.Measurement@1f].
javax.persistence.RollbackException: Exception [EclipseLink-7197] (Eclipse Persistence Services - 1.0.2 (Build 20081024)): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null primary key encountered in unit of work clone [topcare.domain.patient.measurement.Measurement@1f].
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commit(EntityTransactionImpl.java:63)
at topcare.domain.DAOFactory.commit(DAOFactory.java:510)
at topcare.domain.UnitOfWork.commit(UnitOfWork.java:92)
at topcare.service.MeasurementService.createMeasurement(MeasurementService.java:94)
at topcare.ui.struts.measurement.MeasurementAction.execute(MeasurementAction.java:84)
at org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:431)
at org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:236)
at org.apache.struts.action.ActionServlet.process(ActionServlet.java:1196)
at org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:237)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:157)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:214)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardContextValve.invokeInternal(StandardContextValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:152)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:118)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:102)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.core.StandardValveContext.invokeNext(StandardValveContext.java:104)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:520)
at org.apache.catalina.core.ContainerBase.invoke(ContainerBase.java:929)
at org.apache.coyote.tomcat5.CoyoteAdapter.service(CoyoteAdapter.java:160)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:799)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:705)
at org.apache.tomcat.util.net.TcpWorkerThread.runIt(PoolTcpEndpoint.java:577)
at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:683)
at java.lang.Thread.run(Thread.java:595)
Caused by: Exception [EclipseLink-7197] (Eclipse Persistence Services - 1.0.2 (Build 20081024)): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null primary key encountered in unit of work clone [topcare.domain.patient.measurement.Measurement@1f].
at org.eclipse.persistence.exceptions.ValidationException.nullPrimaryKeyInUnitOfWorkClone(ValidationException.java:1305)
at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.calculateChanges(DeferredChangeDetectionPolicy.java:84)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.calculateChanges(UnitOfWorkImpl.java:557)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitToDatabaseWithChangeSet(UnitOfWorkImpl.java:1320)
at org.eclipse.persistence.internal.sessions.RepeatableWriteUnitOfWork.commitRootUnitOfWork(RepeatableWriteUnitOfWork.java:159)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.commitAndResume(UnitOfWorkImpl.java:1002)
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:84)
... 35 more
Thanks for any help