Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate Delete Cascade

I Have one entity [Project] that contains a collection of other entities [Questions].

I have mapped the relation with a cascade attribute of "all-delete-orphan".

In my DB the relation is mapped with a project_id (FK) field on the questions table. this field cannot be null since I don't want a Question without a Project.

When I do session.delete(project) it throws an exception saying that project_id cant be null, but if I remove the not-null constraint to that field, the deletion works nice.

Anyone knows how to solve this?

like image 928
Pablo Fernandez Avatar asked Oct 13 '08 23:10

Pablo Fernandez


People also ask

How do I delete cascade?

Use the ON DELETE CASCADE option to specify whether you want rows deleted in a child table when corresponding rows are deleted in the parent table. If you do not specify cascading deletes, the default behavior of the database server prevents you from deleting data in a table if other tables reference it.

Is on delete cascade bad practice?

Yes, the use of ON DELETE CASCADE is fine, but only when the dependent rows are really a logical extension of the row being deleted. For example, it's OK for DELETE ORDERS to delete the associated ORDER_LINES because clearly, you want to delete this order, which consists of a header and some lines.

What does CascadeType remove do?

As stated earlier, marking a reference field with CascadeType. REMOVE is a way to delete a child entity or entities whenever the deletion of its parent happens. In our case, an OrderRequest has a ShipmentInfo, which has a CascadeType. REMOVE.


1 Answers

Straight from the documentation. This explains your problem exactly i believe:

However, this code

Parent p = (Parent) session.Load(typeof(Parent), pid);
// Get one child out of the set
IEnumerator childEnumerator = p.Children.GetEnumerator();
childEnumerator.MoveNext();
Child c = (Child) childEnumerator.Current;

p.Children.Remove(c);
c.Parent = null;
session.Flush();

will not remove c from the database; it will only remove the link to p (and cause a NOT NULL constraint violation, in this case). You need to explicitly Delete() the Child.

Parent p = (Parent) session.Load(typeof(Parent), pid);
// Get one child out of the set
IEnumerator childEnumerator = p.Children.GetEnumerator();
childEnumerator.MoveNext();
Child c = (Child) childEnumerator.Current;

p.Children.Remove(c);
session.Delete(c);
session.Flush();

Now, in our case, a Child can't really exist without its parent. So if we remove a Child from the collection, we really do want it to be deleted. For this, we must use cascade="all-delete-orphan".

<set name="Children" inverse="true" cascade="all-delete-orphan">
    <key column="parent_id"/>
    <one-to-many class="Child"/>
</set>

Edit:

With regards to the inverse stuff, i believe this only determines how the sql is generated, see this doc for more info.

One thing to note is, have you got

not-null="true"

on the many-to-one relationship in your hibernate config?

like image 53
abarax Avatar answered Oct 05 '22 10:10

abarax