Mixing typed with native queries in Spring Data JPA
Hibernate caches entities for improved performance. After modifying queries the cache is updated. When using native queries within the same transaction, changes are not reflected in the cache. Mixing typed native queries, we need to manually tell hibernate to invalidate the cache manually. I had solved this issue for the first time recently. It took me some time to find a proper solution.
An example to describe my case:
List<Users> users = repository.find()doSomethingWith(users)
updateRating() => native query to recacalculate ratingList<Users> updatedUsers = repository.find() // no update receiveddoMoreWith(users)
In the second find() the updated rating was not available. Hibernate does not know what entities to evict from the cache because of the native query.
Detach
The best solution for this case I found was to detach
the list of entities before loading again:
...
users.forEach(user -> entityManager.detach(user))
List<Users> updatedUsers = repository.find() // got update
Thanks to Thorben Janssen for writing the article about that!
Refresh
Searching for this issue, I found most often to refresh the entity. I would need to refresh each entity, resulting in lots of queries.
Clear
Another way would be to clear the entire cache.
// by annotation on top of Spring JPA Repository methods:
@Modifying(flushAutomatically = true, clearAutomatically = true)// or manually via entityManager:
entityManager.flush()
entityManager.clear()
When clearing the cache, all entities are gone. The result were LazyInitializationExceptions. I would need to reload all entities in my transaction.