Hi, I am trying to understand how to synchronize removed items from colletions in detached objects is made to the db.
I have a web-based 5 step wizard that allows updating of a POF object. At the very start, the whole POF object graph is loaded from the db and then is detached.
As the user steps through the wizard, the detached POF is modified. When it comes to step 3, the user can choose to add or remove elements from the line items collection.
At the very last confirmation step, a call to hibernate is made to update the POF. All changes are made to the main POF, many-to-one associates and if items were ADDED to the line items collecton, these are also persisted. I think this all happens on save because of the cascade="all"
My issue is that if the user has removed line items, when update is called, the line item(s) that were removed in the detached object do not get removed from the database.
I have found several places online and in Hibernate in Action that allude to this but I don't think I am totally getting it. I now have a pof.removeLineItem method that sets the LineItem.pof to null to get rid of that end, and I then also remove the item from the lineItems collection.
I have tried cascade="all-delete-orphan" but this gives me an error
You may not dereference a collection with cascade="all-delete-orphan"
and this error is caused by trying to load the POF as follows
Code:
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Query q = session.createQuery(
"from POF as p " +
" left outer join fetch p.lineItems " +
"where p.id = :pofId"
);
q.setParameter("pofId", id);
pof = (POF) q.list().get(0);
if (pof != null) {
q = session.createQuery(
"from Action as a " +
"where a.purchaseOrderForm.id = :pofId"
);
q.setParameter("pofId", id);
pof.setActionHistory(q.list());
}
tx.commit();
HibernateUtil.closeSession(session);
so overall i am a little confused but on the edge of success if i could just get some tips :)
Hibernate version: 2.1.6
Mapping documents:Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping schema="dbPOF.dbo">
<class name="com.qas.newmedia.intranet.pof.dto.POF"
table="tbl_POFs">
<id name="id" type="int" column="pof_id" unsaved-value="0">
<generator class="identity" />
</id>
<property name="created" column="created" type="calendar" not-null="true" />
<property name="status" column="status" not-null="true" />
<property name="reference" column="reference" not-null="true" />
<property name="externalId" column="external_id" not-null="false" />
<property name="originator" column="originator" not-null="true" />
<property name="originatorFullName" column="originator_full_name" not-null="true" />
<property name="department" column="department" not-null="true" />
<property name="departmentCode" column="department_code" not-null="true" />
<property name="currencyCode" column="currency_code" not-null="true" />
<property name="taxRate">
<column name="tax_rate" not-null="true" sql-type="money" />
</property>
<property name="authoriser" column="authoriser" not-null="true" />
<property name="authoriserFullName" column="authoriser_full_name" not-null="true" />
<property name="appliesToMin" column="applies_to_min" type="calendar" not-null="true" />
<property name="appliesToMax" column="applies_to_max" type="calendar" not-null="true" />
<property name="netCost">
<column name="net_cost" not-null="true" sql-type="money" />
</property>
<property name="discountCost">
<column name="discount_cost" not-null="true" sql-type="money" />
</property>
<property name="carriageCost">
<column name="carriage_cost" not-null="true" sql-type="money" />
</property>
<property name="taxCost">
<column name="tax_cost" not-null="true" sql-type="money" />
</property>
<property name="grossCost">
<column name="gross_cost" not-null="true" sql-type="money" />
</property>
<property name="notes">
<column name="notes" not-null="false" sql-type="varchar(4000)" />
</property>
<many-to-one name="supplier" column="supplier_id" cascade="all" unique="true" />
<many-to-one name="deliveryAddress" column="delivery_address_id" cascade="all" unique="true" />
<list name="lineItems" inverse="true" lazy="true" cascade="all">
<key column="pof_id"/>
<index column="index_col" />
<one-to-many class="com.qas.newmedia.intranet.pof.dto.LineItem" />
</list>
<list name="actionHistory" inverse="true" lazy="true" cascade="all">
<key column="pof_id"/>
<index column="index_col" />
<one-to-many class="com.qas.newmedia.intranet.pof.dto.Action" />
</list>
</class>
<class name="com.qas.newmedia.intranet.pof.dto.LineItem"
table="tbl_LineItems">
<id name="id" type="int" column="line_item_id" unsaved-value="0">
<generator class="identity" />
</id>
<property name="code" column="code" not-null="false" />
<property name="description" column="description" not-null="true" />
<property name="function" column="fn" not-null="false" />
<property name="quantity" column="quantity" type="int" not-null="true" />
<property name="unitPrice">
<column name="unit_price" not-null="true" sql-type="money" />
</property>
<property name="taxType" column="tax_type" not-null="true" />
<property name="netCost">
<column name="net_cost" not-null="true" sql-type="money" />
</property>
<property name="notes">
<column name="notes" not-null="false" sql-type="varchar(4000)" />
</property>
<many-to-one name="purchaseOrderForm" column="pof_id" not-null="true" />
<property name="index" type="int" update="true" insert="true" column="index_col" />
</class>
<class name="com.qas.newmedia.intranet.pof.dto.Supplier"
table="tbl_Suppliers">
<id name="id" type="int" column="supplier_id" unsaved-value="0">
<generator class="identity" />
</id>
<property name="code" column="code" not-null="true" />
<many-to-one name="address" column="address_id" cascade="all" unique="true" />
</class>
<class name="com.qas.newmedia.intranet.pof.dto.IntlCompanyDetail"
table="tbl_IntlCompanyDetails">
<id name="id" type="int" column="intl_comp_det_id" unsaved-value="0">
<generator class="identity" />
</id>
<property name="company" column="company" not-null="false" />
<property name="contact" column="contact" not-null="false" />
<property name="telephone" column="telephone" not-null="false" />
<property name="fax" column="fax" not-null="false" />
<property name="email" column="email" not-null="false" />
<property name="web" column="web" not-null="false" />
<property name="addressLine1" column="address_line_1" not-null="false" />
<property name="addressLine2" column="address_line_2" not-null="false" />
<property name="addressLine3" column="address_line_3" not-null="false" />
<property name="addressLine4" column="address_line_4" not-null="false" />
<property name="addressLine5" column="address_line_5" not-null="false" />
<property name="addressLine6" column="address_line_6" not-null="false" />
<property name="addressLine7" column="address_line_7" not-null="false" />
</class>
<class name="com.qas.newmedia.intranet.pof.dto.Action"
table="tbl_Actions">
<id name="id" type="int" column="action_id" unsaved-value="0">
<generator class="identity" />
</id>
<property name="created" column="created" type="calendar" not-null="false" />
<property name="username" column="username" not-null="false" />
<property name="fullName" column="fullName" not-null="false" />
<property name="department" column="department" not-null="false" />
<property name="action" column="action" not-null="false" />
<many-to-one name="purchaseOrderForm" column="pof_id" not-null="true" />
<property name="index" type="int" update="true" insert="true" column="index_col" />
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
N/a
Full stack trace of any exception that occurs:
N/a
Name and version of the database you are using:
SQL Server 2000
The generated SQL (show_sql=true):
N/a
Debug level Hibernate log excerpt:
N/a