Sounds like you are experiencing the issue where flush cascades PERSIST
back to an entity that was removed.
This was "introduced" by HHH-5124. Previously, Hibernate was really in
violation of the JPA spec, specifically section 3.2.2 which says that
the PERSIST operation applied to some entity X should:
<quote>
If X is a removed entity, it becomes managed.
</quote>
So if remove(it) is immediately followed by persist(it), the persist
should "cancel" the remove. At least that was our reading of "it
becomes managed" here.
The situation here involves another passage from the spec, namely 3.2.4
which talks about flushing and says that when processing an entity X
during flush that:
<quote>
For all entities Y referenced by a relationship from X, if the
relationship to Y has been annotated with the cascade element value
cascade=PERSIST or cascade=ALL, the persist operation is applied to Y.
</quote>
What happens, most likely, is that you have another entity in your
Session/EM that has an association to the Person(s) removed. When that
other entity gets processed by flush, 3.2.4 comes into play and we
cascade (PERSIST) to Person.
This is unexpected and obviously unintended, but it is also clearly what
the spec says should happen. I have asked the spec lead about some
possible options that would probably still meet the intent of the spec
(even if they violate the wording) and would be more "natural".
On Wed 18 Jan 2012 10:17:12 AM CST, Guillaume Smet wrote:
Hi,
In our test cases, we have a test which checks a lot of cascade
configuration (it's more to document all the cascade behaviors than to
really test an application).
After the upgrade from Hibernate 4.0 to Hibernate 4.0.1, we have a test failing:
- a person is linked to a company
- if we delete a company, it should cascade to the persons due to the
annotation @OneToMany(cascade = CascadeType.REMOVE)
Company {
@OneToMany(cascade = CascadeType.REMOVE)
@JoinTable(name="company_employees4",
joinColumns=@JoinColumn(name="company_id"),
inverseJoinColumns=@JoinColumn(name="employees4_id"))
private List<Person> employees4 = new LinkedList<Person>();
}
In the case of a person linked to 2 companies
- we have an exception with Hibernate 4.0: this is what we expect as
the person is linked to another company and the database warns us
about it thanks to the foreign key;
- the delete is OK with 4.0.1 (no exception due to the foreign key)
and if I try to get the person after that, it's still there so it
seems as if the cascade is not triggered at all.
Does it ring a bell to anyone? I don't have a lot of time atm to
extract a self contained test case so if it's something obvious due to
4.0 -> 4.0.1 fixes, I might pass on this one. I checked the release
notes without finding something which can explain this new behavior.
If it's not something obvious, I'll try to work on a test case in the
next few days. If so, pointers to where I should add the test in the
code base are greatly appreciated.
Thanks for your feedback.
Thanks.
--
steve(a)hibernate.org
http://hibernate.org