Hey there,
What I am trying to do is inserting an object plus it's one-to-many associated objects in a single transaction. It's important because the object should not exist without the associated objects, so if something goes wrong the whole transaction should be rolled back.
Hibernate version: 3.1
Mapping documents:
Procedure:
Code:
<hibernate-mapping package="com.package">
<class name="Procedure" table="procedures" schema="public">
<id name="id" type="int">
<column name="procedure_id" />
<generator class="sequence">
<param name="sequence">
procedure_id_seq
</param>
</generator>
</id>
<set name="procedureParameters" inverse="true" cascade="persist,merge,save-update">
<key>
<column name="procedure_id" not-null="true" />
</key>
<one-to-many class="ProcedureParameter" />
</set>
</class>
</hibernate-mapping>
ProcedureParameter:Code:
<hibernate-mapping package="com.package">
<class name="ProcedureParameter" table="procedure_parameters" schema="public">
<composite-id name="id" class="ProcedureParameterId">
<key-property name="parameterCode" type="string">
<column name="parameter_code" length="12" />
</key-property>
<key-property name="procedureId" type="int">
<column name="procedure_id"/>
</key-property>
</composite-id>
<many-to-one name="procedure" class="Procedure" update="false" insert="false" fetch="select">
<column name="procedure_id" not-null="true" />
</many-to-one>
<property name="value" type="string">
<column name="value" length="250" />
</property>
<property name="remarks" type="string">
<column name="remarks" length="100" />
</property>
</class>
</hibernate-mapping>
Objects in question (stubs only):Procedure:Code:
public class Procedure {
private Integer id;
private Set<ProcedureParameter> procedureParameters = new HashSet<ProcedureParameter>(0);
}
ProcedureParameter:Code:
public class ProcedureParameter {
private ProcedureParameterId id;
private String value;
private String remarks;
private Procedure procedure;
}
ProcedureParameterId:Code:
public class ProcedureParameterId {
private String parameterCode;
private Integer procedureId;
}
Normally I would do something like this (everything within one hibernate session):
Code:
BEGIN TRANSACTION 1
Procedure procedure = new Procedure();
HibernateSession.save(procedure);
COMMIT TRANSACTION 1
BEGIN TRANSACTION 2
ProcedureParameter procParam1 = new ProcedureParameter(new ProcedureParameterId("PARAM1", procedure.getId()), "value1", "remark1");
ProcedureParameter procParam2 = new ProcedureParameter(new ProcedureParameterId("PARAM2", procedure.getId()), "value2", "remark2");
procedure.getProcedureParameters().add(procParam1);
procedure.getProcedureParameters().add(procParam2);
// save not needed - cascade will take care of inserting procedure parameters
COMMIT TRANSACTION 2
But as I mentioned before this has to be done in a single transaction. Is there any way to bind ProcedureParameterId.procedureId to Procedure.id so that once created Procedure.id taken from procedure_id_seq would be known "behind the scenes" to ProcedureParameterId.procedureId?
What I would like is something like this:
Code:
BEGIN TRANSACTION
Procedure procedure = new Procedure(); // gets id only at the commit
ProcedureParameter procParam1 = new ProcedureParameter(new ProcedureParameterId("PARAM1", ???), "value1", "remark1");
ProcedureParameter procParam2 = new ProcedureParameter(new ProcedureParameterId("PARAM2", ???), "value2", "remark2");
procedure.getProcedureParameters().add(procParam1);
procedure.getProcedureParameters().add(procParam2);
HibernateSession.save(procedure);
COMMIT TRANSACTION
Any ideas?