Hibernate 一个实体管理器没有';看不到其他EntityManager完成的更新
我在独立应用程序中使用了两个EntityManager实例,其资源为本地事务类型。我执行以下操作:Hibernate 一个实体管理器没有';看不到其他EntityManager完成的更新,hibernate,jpa,Hibernate,Jpa,我在独立应用程序中使用了两个EntityManager实例,其资源为本地事务类型。我执行以下操作: 使用第一个EntityManager(em1)保存实体 使用第二个EntityManager(em2)更新实体 使用第一个EntityManager(em1)读取实体 问题是第三步的em1没有看到em2完成的更新 EntityManagerFactory emf = Persistence.createEntityManagerFactory("test"); // Step 1: crea
- 使用第一个EntityManager(em1)保存实体
- 使用第二个EntityManager(em2)更新实体
- 使用第一个EntityManager(em1)读取实体
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();
有人能解释为什么em1读取陈旧数据吗?如果实体的引用在请求数据库之前存在,则
EntityManager
首先在其一级缓存中查找。em1
变量引用的EntityManager
实例在缓存中保留了id为1
的Article
实体。因此,此语句将从缓存中检索实体:
Article updatedArticle = em1.find(Article.class, 1L);
要防止这种行为,有多种方法:
- 通过调用
将实体从EntityManager上下文中分离EntityManager.detach()
- 通过调用
,从数据库中刷新实体的状态。在这种情况下,不再需要EntityManager.refresh()
查询find()
- 更激进的做法是:通过调用:
EntityManager.clear()
em1.refresh(article);
关于一级缓存:
关于刷新可能会出现许多原因。。。您是否尝试
flush()
或execute()
cahce?所描述的行为通常是已知且正确的。如果是应用程序管理的EntityManager,则为每个事务创建一个新的EntityManager是否是一个好主意?EntityManager
的工作方式是:一个事务一个事务。在阅读代码时,我想知道的问题是,为什么要创建这么多事务?可以将事务同化为客户端请求。如果您有3个不同的请求,那么可以创建3个EntityManager。但这是您的用例吗?基本上,我想测试悲观锁定是如何工作的。这意味着我需要在并发事务中运行读/写操作(即在不同的线程中)。在编写测试时,我观察到EntityManager读取了过时的数据,但不明白为什么。因此,我编写了一个没有线程和锁的简化示例。在本例中,使用多个EM的示例代码就可以了。