Spring Data JPA causes EntityExistsException with cascading save

I have a Challenge class, which has a many to one relationship with a User class. It is uni-directional, so it looks like this:

@Entity
@Table(name="UserTable")
public class User {
   @Id
   private String userId;
}


@Entity
@Table(name="ChallengeTable")
public class Challenge {
   @Id
   private String challengeId;

   @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
   @JoinColumn(name="userId")
   private User user;
}

I'm using Spring Data JPA, and when I use the "save" method from the CRUDRepository on a Challenge object, I want it to persist the attached user if that user doesn't already exist, and merge the user into the old user if it does already exist.

I'm using a "findOne(String id)" method in the UserRepository to get a user using a user Id, and that's the user I'm setting in the Challenge.

It cascades just fine if the user doesn't already exist, but when I try to save it with a pre-existing user I get the exception:

javax.persistence.EntityExistsException: a different object with the same identifier value was already associated with the session: [com.mywebsite.model.User#zk9moo78sx685g6o9yphegdx6lpoll9x]

I'm not sure what I'm doing wrong here. Changing the CascadeType to ALL doesn't change anything. Trying to remove the CascadeType entirely and manually saving the User first doesn't work either. That gives me the error:

org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing: com.mywebsite.model.Challenge.user -> com.mywebsite.model.User

That appears to take place when the transaction exits (as I have my service layer class annotated with @Transactional).

If I take out the @Transactional annotation and manually persist the user it seems to all work fine. (I still want the cascading saves and transactions on the service level though.)

Taking out the @Transactional and trying to use cascading saves fails with a SQLIntegrityConstraintViolationException exception because it seems like the User becomes a detached entity and it tries to persist it anew, but that primary key already exists so it fails.

Can anyone help me understand what's going on here, and help me get cascading saves working with transactions in Spring Data JPA?

Answers


I tried using hibernate-specific cascading options, and everything else I could think of, but I couldn't get cascading saves to work as a Hibernate CascadeType.SAVE_UPDATE is supposed to. I believe it's a hard limitation of JPA with Spring Data.

Instead, I added a layer between the service and the interface repository. It saves the dependent entity (the user) then the challenge.


Need Your Help

Network discovery in .NET

c# networking

I need to get a list of machine connected to the current computer, just like explorer do. I want to use their name to retrieve their shared path using NetShareEnum.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.