Hi I wonder if anyone can help me please. I have a web application which I have just ported over from EJB2 CMP to Hibernate 2.1.4, I am using mySQL 3.23.38. I am having a problem with nested collections. The scenario follows ( & some code follows the scenario). I have looked at the faq, which mentions that I need to manage both ends of the collection in bi-directional associations, but I thought that cascade="all" removed the need to do this? Also it seems to work without setting both ends of the association in the Parent/Child relationship, but runs into problems when the Child has a Grandchild added. I'm sure the solution here is obvious & simple for an experienced user, but I'm a bit stuck :-)
Many many thanks in advance for any help :-)
Paul
Servlet call one - create Parent & use Manager.saveObject(Object ob) method to persist it, add Parent to HttpSession
Servlet call two - get Parent from HttpSession, create Child & then use Manager.addChild(Parent parent, Child child). All is well at this point & both Parent & Child are persisted & in the database I can see the Child's reference to the Parent. Add Child to HttpSession
Servlet call three - get Parent from HttpSession, either get Child from HttpSession or use convenience method on Parent to iterate through collection & get Child from the Parent using it's ID (both methods yield the same end result). Now create Grandchild & use Manager.addGrandchild(Child child, Grandchild grandchild) to persist objects.
This is where the problem occurs, the Grandchild is linked to the Child, but the Child's link to the Parent is set to
null in the database & so it loses the link between Parent & Child. What am I doing wrong & what is the best way to manage this please?
Hibernate config file extracts
Parent.hbm.xml
Code:
<set name="children" table="PARENT" cascade="all" >
<key column="ACCOUNT_ID"/>
<one-to-many class="Child"/>
</set>
Child.hbm.xml
Code:
<many-to-one name="parent" class="PARENT" column="PARENT_ID"/>
<set name="grandchildren" table="CHILD_GRANDCHILDREN" cascade="all">
<key column="CHILD_ID"/>
<many-to-many class="Grandchild" column="GRANDCHILD_ID"/>
</set>
Grandchild.hbm.xml
Code:
<set name="children" table="CHILD_GRANDCHILDREN" inverse="true">
<key column="GRANDCHILD_ID"/>
<many-to-many class="Child" column="CHILD_ID"/>
</set>
Manager methodsCode:
public static void saveObject(Object ob) throws PersistenceException {
try {
Session session = null;
Transaction tx = null;
try {
session = HibernateUtil.openSession();
tx = session.beginTransaction();
session.saveOrUpdate(ob);
tx.commit();
}
catch(StaleObjectStateException e){
if (tx != null) {
tx.rollback();
}
throw new StalePersistentObjectException(e);
}
catch (HibernateException e) {
if (tx != null) {
tx.rollback();
}
throw new PersistenceException(e);
}
finally {
closeSession(session);
}
}
catch (HibernateException e) {
throw new PersistenceException(e);
}
}
public void addChild(Parent parent, Child child) throws PersistenceException {
Session session = null;
Transaction tx = null;
try {
try {
session = HibernateUtil.openSession();
tx = session.beginTransaction();
parent.addChild(child);
session.saveOrUpdate(parent);
tx.commit();
}
catch(StaleObjectStateException e){
LOGGER.debug(e);
if(tx != null){
tx.rollback();
}
throw new StalePersistentObjectException(e);
}
catch (HibernateException e) {
if (tx != null) {
tx.rollback();
}
throw new PersistenceException(e);
}
finally {
HibernateUtil.closeSession(session);
}
}
catch (HibernateException e) {
throw new PersistenceException(e);
}
}
public void addGrandchild(Child child, Grandchild grandchild) throws PersistenceException {
Session session = null;
Transaction tx = null;
try {
try {
session = HibernateUtil.openSession();
tx = session.beginTransaction();
child.addGrandchild(grandchild); // addGrandchild method works like parent.addChild()
Parent parent = child.getParent();
session.saveOrUpdate(parent); // have also tried saving child here instead, but results are always the same
tx.commit();
}
catch (StaleObjectStateException e) {
LOGGER.debug(e);
if(tx != null){
tx.rollback();
}
throw new StalePersistentObjectException(e);
}
catch (HibernateException e) {
if (tx != null) {
tx.rollback();
}
throw new PersistenceException(e);
}
finally {
HibernateUtil.closeSession(session);
}
}
catch (HibernateException e) {
throw new PersistenceException(e);
}
}
Parent methods Code:
public Set getChildren() {
return this.children;
}
public void addChild(Child child){
getChildren().add(child);
}