[hibernate-dev] Hibernate 4.0.1: regression with @OneToMany(cascade = CascadeType.REMOVE)

Steve Ebersole steve at hibernate.org
Wed Jan 18 11:42:10 EST 2012


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 at hibernate.org
http://hibernate.org



More information about the hibernate-dev mailing list