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 constrain to that field, the deletion works nice.
Anyone knows how to solve this?
-
The delete is occurring on the Project first and cascading to the Question, but the Project delete includes a nulling of the project_id in the Questions (for referential integrity. You're not getting an exception on the deletion of the Question object, but because the cascade is trying to null the FK in the Question(s).
Looking at "Java Persistence with Hibernate", I think that what you really want a cascade type of delete or remove, not delete-orphans.
Pablo Fernandez : That does not solve anythingFrom Steve Moyer -
One strategy is to mark the foreign-key in the database with on-delete-cascade, so as soon as NHibernate tells the database to delete a project, the database itself will cascade the deletes. Then you have to tell NHibernate that the database itself does a cascade delete.
Pablo Fernandez : is that posible with nhibernate 1.2?From Justice -
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?
Pablo Fernandez : Sorry. This does work, but I don't understand why. From the docs it says that inverse true is used when you map a bidirectional association (and it's not my case), anyways adding that makes it work nicely. Thanks. If you edit explaining why inverse=true works, I'll accept your answerkbaribeau : Is there an example of this from the hibernate docs? It seems weird to me that he asked about hibernate and you answered with some nhibernate documentation.Abarax : I added some extra info for you. Glad this has worked for you :)From Abarax
0 comments:
Post a Comment