Blog Archives

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)
	@JoinTable(name="QP_Q", 
	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)
	@JoinTable(name="QP_Q", 
	joinColumns={@JoinColumn(name="questionpaperid")}, inverseJoinColumns=@JoinColumn(name="questionid"))
Advertisements