I'm using two EntityManager instances in standalone application with RESOURCE_LOCAL transaction type. I perform such operations:
The problem is that em1 on the 3rd step doesn't see updates done by em2.
EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");
// Step 1: create entity
EntityManager em1 = emf.createEntityManager();
em1.getTransaction().begin();
Article article = new Article("article_1");
em1.persist(article);
em1.getTransaction().commit();
// Step 2: update entity
EntityManager em2 = emf.createEntityManager();
em2.getTransaction().begin();
Article articleForUpdate = em2.find(Article.class, 1L);
articleForUpdate.setName("updated article_1");
em2.persist(articleForUpdate);
em2.getTransaction().commit();
// Step 3: read updated entity
em1.getTransaction().begin();
Article updatedArticle = em1.find(Article.class, 1L);
em1.getTransaction().commit();
log.info("updated entity: {}", updatedArticle); // logs stale data
em1.close();
em2.close();
emf.close();
Can anyone explain why em1 reads stale data?
The EntityManager
looks first in its first level cache if a reference of the entity exists before requesting the database.
The EntityManager
instance referenced by the em1
variable has the Article
entity with the id 1
in cache as it has persisted it.
So this statement will retrieve the entity from the cache :
Article updatedArticle = em1.find(Article.class, 1L);
To prevent this behavior you have multiple ways :
EntityManager.detach()
.EntityManager.refresh()
. In this case, the the find()
query is not any longer required.EntityManager
context by invoking : EntityManager.clear()