Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JPA 2.0 / Hibernate and "orphanRemoval": Just replacing an entity does not remove the old one

I have question regarding JPA 2.0, Hibernate and "orphanRemoval".

First my setup:

  • Spring 3.0.5.RELEASE
  • SprnigData JPA 1.0.1.RELEASE
  • Hibernate 3.5.2-Final
  • DBMS: PostgreSQL 9.0

I have two rather simple entity classes, "User" and "AvatarImage", A "User" has an "AvatarImage", and so between "User" and "AvatarImage" there is the relationship.

In the class "User", the property looks like this:

// class "User"
@OneToOne(cascade = CascadeType.ALL, fetch=FetchType.LAZY, orphanRemoval = true)
private AvatarImage    avatarImage;

So that means, if the "avatarImage" property gets set to null, the reference between "User" and "AvatarImage" is removed and "orphanRemoval" mechanism will delete the "avatarImage" from the database (please correct me if I'm wrong).

So when I update the "avatarImage" for a certain user, I currently have to write this:

user.setAvatarImage( null );  // First set it to null
userRepository.save( user );  // Now "orphanRemoval" will delete the old one

user.setAvatarImage( theNewAvatarImage );
userRepository.save( user );

So setting the "avatarImage" property first to null, saving the "user", and then set the new AvatarImage "theNewAvatarImage", again saving the user.

This is the only way it currently works for me - the "orphanRemoval" will delete the old "avatarImage" on setting it to "null" and then saving the user.

But, I would have thought that this code should also work:

user.setAvatarImage( theNewAvatarImage );
userRepository.save( user );

So I omit setting the "avatarImage" to "null" but just setting "theNewAvatarImage", replacing the old "avatarImage". But this does not work, the old AvatarImage does not get removed from the database upon transaction commit.

Does anyone know, why the second code (just replacing the AvatarImage without setting it to "null" before) does not work?

I really appreciate any help you can offer

Thanks a lot!

like image 762
It's Leto Avatar asked Sep 22 '11 06:09

It's Leto


2 Answers

This is related to Hibernate JIRA tickets HHH-5559 and HHH-6484. By and large, Hibernate, as of today, requires you to set the reference to null and flush the persistence context, before providing a new value to the relationship (see the test case in HHH-6484); it is only in such a case that Hibernate issues a SQL DELETE statement, providing a broken implementation (IMHO) for orphanRemoval.

In short, you'll need to wait for the bugs to be fixed, or write code to nullify references and flush the persistence context, or use a JPA provider that supports orphanRemoval in this manner (EclipseLink 2.3.0 does).

like image 191
Vineet Reynolds Avatar answered Oct 02 '22 10:10

Vineet Reynolds


As of @OneToMany relationship, this is related to Hibernate JIRA ticket HHH-6709. Please vote for these so it get some attention.

like image 22
Arash Avatar answered Oct 02 '22 10:10

Arash