I am trying to implement parent child relation on traditional Order and Items tables. For this I am using uni-directional one-to-many association but I can make either "save" operation work or the "delete", one at a time.
If I set inverse="false"
I can create new order (with items) but can't Delete it because hibernate tries to delete order record first and it fails due to reference in Items table
On the other hand, if I set inverse="true"
then Order can be deleted but not created as it tries to create OrderItems record first that fails due to missing reference in Order table (orderId is not null in Items table)
Bi-directional association is also a pain because it leads to circularities in object graphs. Can anyone suggest me a solution?
My hibernate mapping is:
<class name="Order" table="ORDERS">
<id column="ID" name="id" type="long">
<generator class="native" />
</id>
<property name="orderDate" type="timestamp" />
<property name="customer" type="string" />
<set cascade="all-delete-orphan" name="items" inverse="true" lazy="true">
<key column="orderId" not-null="true" />
<one-to-many class="OrderItem" />
</set>
</class>
<class name="Item" table="Items">
<id column="id" name="itemId" type="long">
<generator class="native" />
</id>
<property name="product" type="string" />
<property name="quantity" type="int" />
</class>
Order.java is:
public class Order implements java.io.Serializable {
private Long id;
private Date orderDate;
private String customer;
private Set<Item> items;
public Long getId() {
return id;
}
public Date getInvDate() {
return invDate;
}
public String getCustomer() {
return customerId;
}
public Set<Item> getItems() {
return items;
}
public void setId(Long id) {
this.id = id;
}
public void setOrderDate(Date orderDate) {
this.orderDate= orderDate;
}
public void setCustomer(String customer) {
this.customer = customer;
}
public void setItems(Set<Item> items) {
this.items = items;
}
}
Item.java
public class Item implements java.io.Serializable {
private Long itemId;
private String product;
private int quantity;
public Long getItemId() {
return itemId;
}
public String getProduct() {
return product;
}
public int getQuantity() {
return quantity;
}
public void setItemId(Long itemId) {
this.itemId = itemId;
}
public void setProduct(String productId) {
this.product = product;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
OrderManager.java
public class OrderManagerBase {
public Long save(Order theOrder) throws RemoteException {
Session session = HbmUtils.getSessionFactory().getCurrentSession();
Transaction tx = null;
Long orderId = null;
try {
tx = session.beginTransaction();
session.persist(theOrder);
tx.commit();
orderId = theOrder.getId();
} catch (RuntimeException e) {
if (tx!=null)
tx.rollback();
throw new RemoteException("Order could not be saved");
}finally{
if (session.isOpen())
session.close();
}
return orderId;
}
public Long delete(Order order) throws RemoteException {
Session session = HbmUtils.getSessionFactory().getCurrentSession();
Transaction tx = null;
Long orderId = order.getId();
try {
tx = session.beginTransaction();
session.delete(order);
tx.commit();
} catch (RuntimeException e) {
tx.rollback();
orderId = null;
}finally{
if (session.isOpen())
session.close();
}
return orderId;
}
public Order getOrder(long cid) throws RemoteException {
Session session = HbmUtils.getSessionFactory().getCurrentSession();
Transaction tx = null;
Order theOrder = null;
try {
tx = session.beginTransaction();
Query q = session.createQuery("from Order as order " +
"left outer join fetch order.items " +
"where order.id = :id").setReadOnly(true);
q.setParameter("id", cid);
theOrder = (Order) q.uniqueResult();
tx.commit();
} catch (RuntimeException e) {
if (tx!=null)
tx.rollback();
e.printStackTrace();
}finally{
if (session.isOpen())
session.close();
}
return theOrder;
}
}
Table are:
CREATE TABLE Orders (
id bigint(20) NOT NULL AUTO_INCREMENT,
orderDate datetime DEFAULT NULL,
PRIMARY KEY (id),
)
CREATE TABLE Items (
id bigint(20) NOT NULL AUTO_INCREMENT,
orderId` bigint(20) NOT NULL,
product varchar(50) DEFAULT NULL,
quantity bigint(20) DEFAULT NULL,
PRIMARY KEY (id),
CONSTRAINT FK_orderitems_1 FOREIGN KEY (orderId) REFERENCES Orderss (id)
)