-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 
Author Message
 Post subject: Parent / child relationship: deleting the parent
PostPosted: Fri Apr 07, 2006 11:23 am 
Newbie

Joined: Fri Apr 07, 2006 10:52 am
Posts: 17
Hi,

I am working with Hibernate 3.1.1 on PostgreSQL 8.1.0 and I have a very basic problem with a parent/child relationship and deletes.

I have a Parent object called Layout, with a simple one-to-one relationship to a child object called Cell. What I want, is that when I delete the parent object, Layout, the child object Cell is deleted too.

I am using many-to-one mapping and not one-to-one mapping. The simplified code of the two classes is as follows:

Parent class:

Code:
public class Layout {
    private Cell cell;
    public void setCell(Cell cell) {
        this.cell = cell;
    }
    public Cell getCell() {
        return this.cell;
    }
}


Child class:
Code:
public class Cell {
    private Layout layout;
    public void setLayout(Layout layout) {
        this.layout = layout;
    }

    public Layout getLayout() {
        return this.layout;
    }
}


When a Layout is created, here's what happens:

Code:
Layout l = new Layout();
l.setCell(new Cell());
l.getCell().setLayout(l);


As you can see, there is a two-directional relationship between the two objects. The two objects are mapped as follows (only the relevant part is here):

Code:
<class name="my.company.layout.Layout" table="CELL" lazy="false">
  <!-- id and other fields are here and work perfectly -->
  <many-to-one name="cell" class="my.company.cell.Cell"
      cascade="all" lazy="false">
      <column name="CELL_ID" sql-type="NUMERIC(18,0)" unique="true" />
  </many-to-one>
</class>


Code:
<class name="my.company.cell.Cell" table="CELL" lazy="false">
  <!-- id and other fields are here and work perfectly -->
  <many-to-one name="layout"
    class="my.company.layout.Layout" cascade="all">
      <column name="LAYOUT_ID" sql-type="NUMERIC(18,0)" unique="true" not-null="false" />
    </many-to-one>
</class>


When I try to delete a Layout, here's what I do:

Code:
Transaction tx = getHibernateSession().createTransaction();
getHibernateSession().createQuery("DELETE FROM Layout WHERE ID=" + id").executeUpdate();
tx.commit();


The generated SQL and error is as follows:

Code:
Hibernate: insert into HT_LAYOUT select bulk_target.PID as PID from LAYOUT bulk_target inner join PRODUCT bulk_target_1_ on bulk_target.PID=bulk_target_1_.ID where PID=185
Hibernate: delete from LAYOUT_SPOOL where (PID) IN (select PID from HT_LAYOUT)
Hibernate: delete from LAYOUT_SHEET where (PID) IN (select PID from HT_LAYOUT)
Hibernate: delete from LAYOUT where (PID) IN (select PID from HT_LAYOUT)
WARN  - SQL Error: 0, SQLState: 23503
ERROR - ERROR: update or delete on "layout" violates foreign key constraint "fk1f8162dfc85e53" on "cell"
  Dettaglio: Key (pid)=(185) is still referenced from table "cell".
WARN  - unable to drop temporary id table after use
org.postgresql.util.PSQLException: ERROR: current transaction is aborted, commands ignored until end of transaction block
[...]
ERROR - org.hibernate.exception.ConstraintViolationException: error performing bulk delete
[...]
Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on "layout" violates foreign key constraint "fk1f8162dfc85e53" on "cell"
  Dettaglio: Key (pid)=(185) is still referenced from table "cell".


The multiple deletes are due to the fact that Layout is really a joined subclass but this is not the point here.

Hibernate is trying to delete the parent table first, when it should delete the child table first. Of course, this causes a foreign key constraint failure because the child table still contains a reference to the parent table and the delete cannot be performed.

What am I doing wrong and why is this happening?

Please note that in my first implementation, only the parent had a reference to the child, so upon deleting the parent, the parent would get deleted but the child would not be deleted, resulting in the database being filled with orphan children.

Thanks in advance for your time.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 07, 2006 12:17 pm 
Newbie

Joined: Thu Apr 06, 2006 4:04 pm
Posts: 9
use not null = "true" in the mapping class.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 07, 2006 12:18 pm 
Newbie

Joined: Thu Apr 06, 2006 4:04 pm
Posts: 9
sorry, use not-null = "true" in the mapping class for the parent.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 07, 2006 12:39 pm 
Newbie

Joined: Fri Apr 07, 2006 10:52 am
Posts: 17
Unfortunately, it does not seem to work. I have tried to set not-null="true" to both the child reference int the parent, an to the parent reference in the child separately and it is still giving the same error, attempting to delete the parent first :(


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 07, 2006 1:22 pm 
Newbie

Joined: Thu Apr 06, 2006 4:04 pm
Posts: 9
http://www.hibernate.org/hib_docs/v3/re ... child.html
http://www.hibernate.org/hib_docs/nhibe ... child.html

Hope this might be helpful.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 07, 2006 2:54 pm 
Newbie

Joined: Thu Apr 06, 2006 4:04 pm
Posts: 9
try

<many-to-one name="layout" class="my.company.layout.Layout" on-delete="cascade"/>

So that child entries are deleted when the parent goes away


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 07, 2006 7:50 pm 
Beginner
Beginner

Joined: Wed Jun 15, 2005 7:14 pm
Posts: 28
Instead of cascade="all", you might try cascade="all-delete-orphan" on the parent because that way, it will delete the orphaned child. "all" only includes everything but the delete orphan stuff. (See section 21.3 of the docs on Cascading Lifecycle in the Parent/Child example)
Why do you need a cascade on the child?
I'm relatively new but I would like to help where I can. So I hope this makes sense and helps :-P.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Apr 10, 2006 5:25 am 
Newbie

Joined: Fri Apr 07, 2006 10:52 am
Posts: 17
Hi again and thanks for the replies. Unfortunately I am still unable to solve the problem and beginning to feel stupid.

After trying all your suggestions, none being successful, I tried to change the mapping strategy using the bidirectional one-to-one mapping strategy, straight out of the manual.

Parent mapping:
Code:
<class name="my.company.layout.Layout" table="LAYOUT" lazy="false">
  <many-to-one name="cell" class="my.company.cell.Cell"
    cascade="all" lazy="false">
        <column name="CELL_ID" sql-type="NUMERIC(18,0)"
        unique="true" not-null="true"/>
   </many-to-one>
</class>

Child mapping:
Code:
<class name="my.company.cell.Cell" table="CELL" lazy="false">
  <one-to-one name="layout"
    class="my.company.layout.Layout"
    property-ref="cell"
    cascade="all">
  </one-to-one>
</class>

Even this does not delete the child at all.

The SQL I get is the following:
Code:
Hibernate: insert into HT_LAYOUT select bulk_target.PID as PID from LAYOUT bulk_target inner join PRODUCT bulk_target_1_ on bulk_target.PID=bulk_target_1_.ID where PID=6
Hibernate: delete from LAYOUT_SPOOL where (PID) IN (select PID from HT_LAYOUT)
Hibernate: delete from LAYOUT_SHEET where (PID) IN (select PID from HT_LAYOUT)
Hibernate: delete from LAYOUT where (PID) IN (select PID from HT_LAYOUT)
Hibernate: delete from PRODUCT where (ID) IN (select PID from HT_LAYOUT)

As you can see, there is no trace whatsoever of any reference of the CELL table.

Before you ask, please note that my class hierarchy is the following:

public class Product
public abstract class Layout extends Product
public class SheetLayout extends Layout
public class SpoolLayout extends Layout

This explains the queries above: the values to be deleted all share the same primary key PID (ProductID) and are stored in a temporary table by hibernate. However, Hibernate won't delete anything below the Layout structure.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 20, 2006 11:07 am 
Newbie

Joined: Fri Apr 07, 2006 10:52 am
Posts: 17
Hi again.

I dropped by to post the solution I found in case somebody might find this useful.

It seems that, in some way, I had overestimated what HQL could do. I was probably expecting too much even if now it just seems obvious.

I was trying to delete a mapped object from the persistent storage using an HQL query like "DELETE FROM ObjectClassName". This is just plain wrong. This would issue an equivalent SQL query to the corresponding table. However, this is not quite right.

All I had to do was to issue a simple session.delete(ObjectInstance). After I tried this, it all worked with no problem even with my original mapping, that I rolled back to.

Thanks to all the people who tried to help.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.