tags:

views:

37

answers:

1

I am facing a problem with parent child type relations.
Hibernate docs say to add a "many-to-one" relation in child class to get value of foreign key from parent. But to make this relation work I have to add Invoice property in child class that introduce a circular inclusion of parent into child and breaks my serializer. Could somebody point where am I doing mistake?

Here is my code:

Invoice.java

public class Invoice implements Serializable {
  private Long id;
  private Date invDate;
  private String customer;
  private Set<InvoiceItem> items;
  ... getters/setters ...
}

InvoiceItem.java

public class InvoiceItem implements Serializable {
  private Long itemId;
  private long productId;
  private int quantity;
  private double price;
  private Invoice invoice; //???????
  ... getters/setters ...
}

Invoice.hbm.xml

<class name="Invoice" table="Invoices">
  <id name="id" column="ID" type="long">
    <generator class="native" />
  </id>
  <property name="invDate" type="timestamp" />
  <property name="customer" type="string" />

  <set name="items" inverse="true" cascade="all-delete-orphan">
    <key column="invoiceId" />
    <one-to-many class="InvoiceItem" />
  </set>
</class>

InvoiceItem.hbm.xml

<class name="InvoiceItem" table="InvoiceItems">
  <id name="itemId" type="long" column="id">
    <generator class="native" />
  </id>

  <property name="productId" type="long" />
  <property name="quantity" type="int" />
  <property name="price" type="double" />

<many-to-one name="invoiceId" class="Invoice" not-null="true"/> <!--????????-->
</class>
+2  A: 

You don't have to have a reference to Invoice in InvoiceItem if you remove the inverse="true" attribute. Hibernate will then create a separate mapping table rather than use a foreign key in the InvoiceItem table.

Remove the inverse attribute on the InvoiceItem set, and also remove the Invoice property from InvoiceItem, and the corresponding many-to-one in the mapping and you should get what you want.

Alternatively, you could mark the Invoice reference in InvoiceItem as transient, and handle populating the value during deserialization: iterate over the Set of Items in Invoice, and set the invoice property on each item to the owning invoice.

mdma
I tried first option but getting error: "Field 'invoiceId' doesn't have a default value". (BTW Foreign key is notNull in DB and I dont want to make it nullable). Here hibernate docs suggest to add many-to-one relation in child class that I am trying to avoid
Leslie Norman
forgot to mention, add not-null="true" to the <key> element under <set> in Invoice.
mdma
great. Both approaches work. Is any of them prefered over the other?
Leslie Norman
Using a unidirectional mapping (without the reference from child back to parent) is sometimes simpler, since you don't have consistency to worry about, but which is best depends upon if you need the child->parent reference or not.
mdma
Thanks mdma for your support
Leslie Norman