Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [eclipselink-users] i encountere a Null primary key in some unit of work clone

The defaultInsertObjectQueryRedirector is something new for grid integration,
for stored procedures support you would normally override the insertCall on
the descriptor's query manager.

descriptor.getQueryManager().setInsertCal(procedureCall);

The arguments to the call must be the mapped field names.  To return a value
for the id you would need to use the ReturningPolicy, as you have done
already.

You could probably also get the redirector to work, but you would need to
refresh the object's ChangeSet after setting the id.

Something like:
query.getChangeSet().removeChange("id");
query.getChangeSet().addChange(descriptor.getObjectBuilder().getMappingForAttributeName("id").compareForChange(query.getObject(),
((UnitOfWorkImpl)session).getBackupClone(query.getObject(), descriptor),
query.getChangeSet(), session));




Rodrigue Lagoue Njinthe wrote:
> 
> 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 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();
>                     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
> 
> 


-----
---
http://wiki.eclipse.org/User:James.sutherland.oracle.com James Sutherland 
http://www.eclipse.org/eclipselink/
 EclipseLink ,  http://www.oracle.com/technology/products/ias/toplink/
TopLink 
Wiki:  http://wiki.eclipse.org/EclipseLink EclipseLink , 
http://wiki.oracle.com/page/TopLink TopLink 
Forums:  http://forums.oracle.com/forums/forum.jspa?forumID=48 TopLink , 
http://www.nabble.com/EclipseLink-f26430.html EclipseLink 
Book:  http://en.wikibooks.org/wiki/Java_Persistence Java Persistence 
-- 
View this message in context: http://www.nabble.com/i-encountere-a-Null-primary-key-in-some-unit-of-work-clone-tp20931083p20934836.html
Sent from the EclipseLink - Users mailing list archive at Nabble.com.



Back to the top