We have an issue that sound like a bug in Hibernate dealing with orphanRemoval=true for a oneToMany List (with index).
Here is the simplified mapping :
public class ParentClass {
[...]
@OneToMany(cascade = ALL, mappedBy = "parent", orphanRemoval = true)
@OnDelete(action = OnDeleteAction.CASCADE)
@Fetch(FetchMode.JOIN)
@OrderColumn(name = "pos", nullable = false)
public List<ChildClass> getChildren() {
return children;
}
}
And the child class :
public class ChildClass {
[...]
@ManyToOne
@JoinColumn(nullable = false, name = "parent_id")
public ParentClass getParent() {
return parent;
}
}
Given this mapping, the following scenario is failing :
Here is the code
@Transactional
public void test() {
// 1)
ParentClass parent = entityManager.find(ParentClass.class, "some-id");
// 2)
ChildClass child = new ChildClass(parent);
parent.getChildren().add(child);
// 3)
entityManager.find(SomethingElse.class, "2");
// 4)
parent.getChildren().remove(child);
}
In that case, the child allocation is inserted into DB and not removed at te end of the transaction.
However, if we don't do step 3), the child allocation is correctly not persisted in DB
Is that a bug ? A wrong mapping ? Is there a workaround for it ?
Yes, that is a bug. I bet you don't use the last version of Hibernate (4.3.8), and that it is related (if not the same issue) to this issue: [HHH-9330] orphanRemoval=true does not work in bidirectional relationships (without cascading) Even if you use the last version, this bug could still exist. If so, please report it and then report the URL to the bug here somewhere. Workaround: try adding the child only when sure it must be persisted or also try setting to null the parent in the child:
child.setParent(null);
Also as another workaround you may try using Hibernate sessions, instead of EntityManager (as it is written in Hibernate's forum).