Persisting a detached entity in JPA

In a JPA many to many relationship, if cascade type has been set at CascadeType.PERSIST (or CascadeType.ALL, which includes CascadeType.PERSIST), then while saving the parent and updating it with references of the child, it will try to save the child again.

	@ManyToMany(cascade={CascadeType.PERSIST,CascadeType.MERGE,CascadeType.REFRESH},fetch = FetchType.EAGER)
	joinColumns={@JoinColumn(name="questionpaperid")}, inverseJoinColumns=@JoinColumn(name="questionid"))

Following issues can appear

  1. Child is already in persistence store (A detached instance has been passed) -in this case it will throw an exception “org.hibernate.PersistentObjectException: detached entity passed to persist”
  2. Child is a new entry, then it will be added in its table and operation will complete successfully

Following are some solutions

  1. If requirement is that Parent should add a existing but detached child(creating an instance with same ID and passing on from the client) -it needs to be reattached to session first. Hmm -for this there is NO way in JPA -Nope, merge does not reattach and entity. If you are using hibernate, you are lucky, merge can do the trick
    For JPA, best option would be to query for entity on server side before trying to save it.
  2. If its sure that only new child will be added, and not an detached instance from DB, CascadeType.PERSIST will take care of
  3. On the other hand, if requirement is never to add a new child if its not alredy in DB then CascadeType.PERSIST should be removed and cascade={CascadeType.MERGE,CascadeType.REFRESH} should be used
	@ManyToMany(cascade={CascadeType.MERGE,CascadeType.REFRESH},fetch = FetchType.EAGER)
	joinColumns={@JoinColumn(name="questionpaperid")}, inverseJoinColumns=@JoinColumn(name="questionid"))

About ChandanPandey

Try to come up with a good design as by product of good coding practices

Posted on December 22, 2012, in Hibernate, Java and tagged , . Bookmark the permalink. 10 Comments.

  1. Hi:

    Excellent and to the point.

  2. Paulo Henrique Heidemann

    After hours lost, finally someone who gets to the point
    Thanks, and excellent post

  3. aliaksei_melnikau

    Thanks man. This post helped a lot.

  4. Big thanks for this post. Solved a problem I have been struggling with for HOURS!

  5. Very helpful, you saved me a lot of time. Thank you!

  6. Thanks a lot its very use full. finally i got ans.

  7. I was facing a similar issue, but I found a solution and the problem is not with JPA. Cascade.MERGE implies that a child will be merged when a parent is merged. In your case I am guessing that you are retrieving the existing parent from the db using entity manager and trying to update its fields and then do a jpa merge in the same transaction. During the updating of the entity you are setting a detached instance of a child to this entity in persistence context. when you do an em.merge, you are trying to merge an entity that is already in the persistence context. Thus em.merge will not merge the parent entity, thus none of your detached children are merged.


    You need to call ‘ em.detach(entity) ‘ before ’em.merge(entity)’,
    This ensures that the parent is merged every time you call em.merge().

  8. really helpful! i have finally resolved my issue with your post’s help 🙂

  9. T H A N K S MAN!!!

  10. Your post saved me from further waste of time…. Awesome and to the point.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: