首页 > 解决方案 > 在调用 @PreUpdate 之前 JPA 刷新到数据库

问题描述

为了创建卷影副本,我试图在执行保存之前捕获数据库中的实体数据。

EntityListener我在我的 Spring 应用程序中实现了以下内容:

    public class CmsListener {
        
        public CmsListener() {
        }
        
        
        
        @PreUpdate
        private void createShadow(CmsModel entity) {
            EntityManager em = BeanUtility.getBean(EntityManager.class);
    
            CmsModel p = em.find(entity.getClass(), entity.getId());
            
            System.out.println(entity);
    
        }
        
    }

entity确实包含要保存的实体对象,然后我使用另一个工具注入它EntityManager,它工作正常 - 但由于某种原因,实体已经保存到数据库中。结果的输出是CmsModel p = em.find(...)相同的数据,位于entity.

为什么在调用 @PreUpdate 之前 JPA/hibernate 会保留更改?我怎样才能防止这种情况?

标签: javaspring-boothibernatejpapersistence

解决方案


我认为这是因为 em.find 实际上并没有查询数据库,而是从缓存中获取对象,所以它实际上获取了相同的对象实体引用(已经应用了更改)。

您可以检查数据库日志以获取获取 entity.id 数据的查询,以验证确实是这种情况,或者您可以在 createShadow() 中添加断点并在函数运行时查看实体的数据库条目调用以亲自查看更改是否已应用于当时的数据库。

要真正解决您的问题并获取卷影副本,您可以通过本机查询直接从数据库中获取对象。这是一个未经测试的示例:

public CmsModel fetchCmsModelDirectly(){
   Query q = em.createNativeQuery("SELECT cm.id,cm.value_a,cm.value_b FROM CmsModel cm",   CmsModel.class);

   try{
      return q.getSingleResult();
   }catch(NoResultException e){
      return null;
   }
}

推荐阅读