views:

168

answers:

1

I have a User and a set of Authorities in a one-to-many relationship:

User.hbm.xml:

<set name="authorities" table="authorities" cascade="all-delete-orphan">
    <key column="user_id" />
    <one-to-many class="com.ebisent.domain.Authority" />
</set>

When I delete a user, I want to delete the authorities as well, but what is happening is that the child table's foreign key (authorities.user_id) is set to null instead. Then I get the following error and the User delete is rolled back:

org.hibernate.StaleStateException: Batch update returned unexpected row count from update [0]; actual row count: 0; expected: 1

The authorities.user_id update to null is not rolled back, however.

How can I delete Authorities when I delete the parent User?

EDIT: I got this working by explicitly deleting the authorities, calling refresh() on the user, then deleting the user, but I would like to know the "right" way to do this.

A: 

This is weird, a cascade all-delete-orphan should cascade the delete operation from the parent to the children. So the following should suffice to get the children deleted:

Parent p = (Parent) session.load(Parent.class, pid);
session.delete(p);
session.flush();

Do you get a different result when using all,delete-orphan or even more simply delete (you shouldn't). Is the assocation bidirectional? If yes, could you show the other side and the corresponding mapping?

The association is only from parent to child, and I get the same results with all, delete-orphan, and delete, BUT...I didn't have session.flush(), and that appears to solve the problem.

The explicit flush might help. But it shouldn't be necessary. I think that defining the foreign key as non nullable would help to get the correct behavior:

<set name="authorities" table="authorities" cascade="all-delete-orphan">
    <key column="user_id" not-null="true"/>
    <one-to-many class="com.ebisent.domain.Authority" />
</set>

Not tested though.

Pascal Thivent
Wouldn't you need an inverse="true" on the relation to have the child records actually deleted ?
nos
Hi, Pascal, nos. The association is only from parent to child, and I get the same results with all, delete-orphan, and delete, BUT...I didn't have session.flush(), and that appears to solve the problem. Thanks!
robert
@nos IMO, `inverse=true` shouldn't be necessary with a uni-directional association.
Pascal Thivent