Hello,
I encounter strange behavior of Hibernate, when using all-delete-orphan cascade.
I will the describe the case. I have simple parent/child relationship. It is a birectional (inverse) relationship with not-null contraint . The problem accours while deleting the orphan. I remove it from collection using simple method (i simplified my original code, so typos will appear :/)
Code:
public class Parent extends Persistent {
[...]
public Child removeChild( Long id ) {
Child child = (Child)EntityHelper.removeEntityFromSet(id, this.childs);
child.setParent(null);
return child;
}
public class EntityHelper {
static public Persistent removeEntityFromSet(Long id, Set set){
Iterator ite = set.iterator();
while ( ite.hasNext() ) {
Persistent entity = (Persistent) ite.next();
if ( entity.getId() != null && entity.getId().equals( id ) ) {
ite.remove();
return entity;
}
}
return null;
}
}
After this operation (and some other), I saveOrUpdate the parent
object and get exception shown below:
Code:
net.sf.hibernate.PropertyValueException: not-null property references a null or transient value: package.Child.parent
(real exceptions are shown at the end of the post)
I suspect that the problem is with child.setParent(null) in removeChild method. Test confirmed my suspicions. I commented the line with setParent(null) and orphan is deleted.
Why hibernate check the nullability?
I think the setParent(null) while removing from collection is very important.
It is as important as setting child.setParent(parent) while adding to collection. It keeps integrity of object model. Why this isn't permitted in hibernate?
Real data:
Hibernate version: 2.1.5
Mapping documents:Udogodnienie (Child):
Code:
<many-to-one
name="jednostkaRM"
class="pl.rynekmedyczny.entity.JednostkaRM"
cascade="none"
outer-join="auto"
update="true"
insert="true"
access="property"
column="jednostka_rm_id"
not-null="true"
/>
JednostkaRM (parent with child collection):
Code:
<set
name="udogodnienia"
lazy="true"
inverse="true"
cascade="all-delete-orphan"
sort="natural"
>
<key
column="jednostka_rm_id"
>
</key>
<one-to-many
class="pl.rynekmedyczny.entity.Udogodnienie"
/>
</set>
Full stack trace of any exception that occurs:Code:
net.sf.hibernate.PropertyValueException: not-null property references a null or transient value: pl.rynekmedyczny.entity.Choroba.komorka
at net.sf.hibernate.impl.SessionImpl.checkNullability(SessionImpl.java:1277)
at net.sf.hibernate.impl.SessionImpl.doDelete(SessionImpl.java:1245)
at net.sf.hibernate.impl.SessionImpl.delete(SessionImpl.java:1173)
at net.sf.hibernate.engine.Cascades.deleteOrphans(Cascades.java:545)
at net.sf.hibernate.engine.Cascades.cascadeCollection(Cascades.java:533)
at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:452)
at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:503)
at net.sf.hibernate.engine.Cascades.cascade(Cascades.java:482)
at net.sf.hibernate.impl.SessionImpl.doUpdate(SessionImpl.java:1475)
at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:1404)
Name and version of the database you are using:
postgreSQL 7.4.5