Search code examples
springhibernatejpaspring-data-jpa

Detached entity is unexpectedly being flushed causing error


Working on an old project, using Spring 3.2.1, Spring Data JPA 1.3.0 with Hibernate 4.1.9 and hibernate-jpa-2.0-api:1.0.1.Final.

This is all happening inside a single transaction.

  1. I retrieve an entity from my implementation of CrudRepository and use some of its data.
  2. Then I detach that entity manually by using entityManager.detach(entity);.
  3. In the following line I fetch another entity from another implementation of CrudRepository.
  4. When fetching the entity in step 3, JPA auto flush is triggered. During the auto flush, an error occurs saying detached entity passed to persist.

I understand the meaning of the message, but I don't understand why it tries to persist the detached entity in the first place. My understanding was that the detach operation removes the element from the persistence context, so during auto flush of the persistence context, the detached entity shouldn't be flushed since it isn't a part of the persistence context anymore. But that's obviously not the case.

I found a question describing the exact same situation: "Detached entity passed to persist" despite flush(), but it wasn't answered directly. The answer said to use entityManager.clear(), but that clears the whole persistence context which is not what I need. I need to detach just this one entity and keep the other entities managed.

The reason I need to detach this one entity is because of some concurrency problems and unwanted overwriting of the entity state in the database.


Solution

  • I encountered the same problem. In my case I had a bi-directional parent-child relationship, and I updated some of the children with a @Modifying JPQL-query. Since the managed entities are not updated automatically, I wanted to detach the affected children and re-fetch them from the database instead of clearing the entire PersistenceContext.

    Inspired by Chris's comment I was able to solve it by cascading the DETACH operation towards the parent entity in my ManyToOne-annotation. That's with the assumption that the side-effect of detaching the parent is acceptable.