tags:

views:

447

answers:

1

Hibernate is not deleting orphans when I set the collection to null, although orphans are deleted when the collection is cleared. I have the following associations.

D - entity, contains a single embedded E
E - embedded object, contains one to many relationship with F (cascade type all,DELETE_ORPHAN)
F - entity, contains a collection of Strings

Note that because E is embedded in D, in the database E has no identity outside of D. Thus I will refer to D/E as a unit. Also notice that F contains a collection of Strings. Due to limitations in hibernate, this means that F must be an entity, not an embeddable value type. The cascade types of the collection of Fs in E include all and DELETE_ORPHAN.

If I want to remove the collection of Fs from D/E, I could explicitly clear all the Fs out of the collection, like this.

D d = //get a reference to a D
E e = d.getE();
Set<F> fs = e.getFs();
fs.clear();
//... update d in the session

This correctly removes all the database rows for Fs pertaining to D/E from the F table and the pertinent rows from the D/E to F join table, as I would expect. However, say I wanted to set the collection of Fs to null, like this.

D d = //get a reference to a D
E e = d.getE();
e.setFs(null);
//... update d in the session

Although this deletes the relationship between D/E and F in the join table, it does NOT remove the database rows for the Fs pertaining to D/E from the F table. Those database rows are now orphaned.

Is there a hibernate setting that allows one to set the collection of Fs to null and have hibernate realize that all Fs in that original collection are now orphaned?

+4  A: 

And how do you suppose Hibernate would know that it should delete all your F entities?

Transitive persistence requires reachability; in order for Hibernate to know that all (or some) collection elements have been deleted it replaces your collection classes with its own that track those changes.

You should never remove the reference to collection once created / instantiated; if you do the changes are lost (either silently behind the scenes or you may get an exception in some cases).

Using clear() is the correct way to tell Hibernate you want collection elements deleted.

ChssPly76
Thanks for the info! Now, the F entities aren't deleted when E gets set to null either. Is this also due to lack of reachability? Would there be a better way to structure these associations to delete the F orphans when E gets set to null?
Jason Novak
If `E` is indeed **embedded**, setting it to null is exactly the same (from Hibernate's standpoint) as setting collection of `F` to null (see the chapter on components in Hibernate documentation). If `E` were an entity you'd either have to delete it explicitly or, if it were itself a collection element on `D`, you could remove it from collection assuming cascade=all-delete-orphan on it.
ChssPly76