【问题标题】:JPA flushing to Database before @PreUpdate is called在调用 @PreUpdate 之前 JPA 刷新到数据库
【发布时间】:2020-10-20 20:47:55
【问题描述】:

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

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

    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 中的数据相同。

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

【问题讨论】:

    标签: java spring-boot hibernate jpa persistence


    【解决方案1】:

    我认为这是因为 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;
       }
    }
    

    【讨论】:

      【解决方案2】:

      你检查实体是否真的更新到数据库?我怀疑更改仅更新到持久性上下文(缓存)。并且当实体在侦听器处查询回来时,将返回缓存中的实体。所以它们是相同的。

      这是大多数 ORM(在本例中为 JPA)的默认行为,用于加快数据查找。 ORM 框架将负责持久化上下文和数据库之间的同步。通常在事务提交时。

      【讨论】:

      • 实体在数据库中-NOT-,但是在查询ORM时它显示它在那里。
      • 所以 - 我有一个自定义 repo,它在实体上执行 refresh(),它从数据库中获取最新数据。当我调用刷新时,它会恢复到之前的状态。这是意料之中的。我没想到的是,我通过查询数据库创建了一个新的实体实例,并在上面调用了refresh()。在这种情况下,缓存的保存模型和新实例都恢复到数据库的当前状态。有没有办法创建一个实体的实例,它不会作为对另一个的引用出现?
      • 据我所知,这不是它在 EntityManager/Persistence 上下文方面的工作方式。实体缓存在持久层/上下文中。从应用程序中查找/创建实体的位置无关紧要。返回来自持久层的相同实例。而且不必每次查找实体时,持久层都会从数据库中查找数据。
      猜你喜欢
      • 2011-03-25
      • 1970-01-01
      • 1970-01-01
      • 2019-05-19
      • 2011-05-23
      • 1970-01-01
      • 1970-01-01
      • 2010-12-25
      • 1970-01-01
      相关资源
      最近更新 更多