【问题标题】:EntityManager refreshEntityManager 刷新
【发布时间】:2011-08-15 12:02:04
【问题描述】:

我有使用 JPA 的 Web 应用程序。这个实体管理器保留了一堆实体,突然我从另一端更新了数据库。我使用 MySQL 并使用 PhpMyAdmin 并更改一些行。

如何告诉实体管理器重新同步,例如忘记缓存中的所有实体?

我知道有refresh(Object) 方法,但是有没有可能怎么做refreshAll() 或者什么结果?

肯定这是昂贵的操作,但如果必须这样做的话。

【问题讨论】:

    标签: java jpa entitymanager


    【解决方案1】:
    entityManager.getEntityManagerFactory().getCache().evictAll()
    

    Refresh 有所不同,因为它修改了您的对象。此行将只是 empty the cache,因此如果您在实体管理器之外获取更改的对象,它将执行实际的数据库查询,而不是使用过时的 cached 值。

    【讨论】:

    • 我知道这是几年前的事,但我想投入两分钱。我不确定这是否可以称为答案。 evictAll() 适用于您希望持久化/合并新数据以忽略缓存内容并强制更新/插入数据库的情况。但是, evictAll() 在首先后端数据库更改值然后您希望从数据存储中提取时显示更改的情况下(至少对我而言)不起作用。根据我的经验,缓存仍然会覆盖后端更改的内容。
    • @JasonWasho,你有解决缓存问题的方法吗?
    • entityManager.clear() 清空持久性上下文。这会导致实体再次从数据库中获取。
    • entityManager.clear() 是唯一对我们有用的东西。不幸的是,它会触发对每个实体的查询。
    【解决方案2】:

    我遇到了类似的问题,上面的 evictAll() 行对我有用。

    或者,实体类上的 @Cache 注释也可以工作,其好处是能够控制缓存参数:

    @Cache(coordinationType=CacheCoordinationType.INVALIDATE_CHANGED_OBJECTS)
    

    见:http://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching

    【讨论】:

      【解决方案3】:

      如果您使用的是 EclipseLink 而不是 Hibernate,则提示是:

      em.createNamedQuery("SomeEntity.SomeNamedQuery")
      .setHint(QueryHints.REFRESH, true)
      .getResultList();
      

      【讨论】:

        【解决方案4】:

        好吧,对于一些尝试添加 factory.getCache().evictAll(); 并且不起作用并且使用 JPA + Hibernate 来刷新查询的人(比如我)将提示 org.hibernate.cacheMode 添加到 IGNORE。示例:

        em.createNamedQuery("SomeEntity.SomeNamedQuery")
          .setHint("org.hibernate.cacheMode", "IGNORE")
          .getResultList();
        

        【讨论】:

          【解决方案5】:

          cache.evictAll 对我不起作用。因此,要检索从另一个应用推送的数据,我执行以下操作:

          em.getTransaction().begin();
          em.getTransaction().commit();
          

          之后,我的 find 查询检索刷新的数据。我不知道这是否是非常安全的解决方案,但它可以正常工作。

          【讨论】:

            【解决方案6】:

            当您将一个对象读入 EntityManager 时,它会成为持久性上下文的一部分,并且相同的对象将保留在 EntityManager 中,直到您 clear() 它并获得一个新的 EntityManager。 因此,如果您更新数据库,除非您在对象上调用 refresh() 或 clear() EntityManager,否则 EntityManager 不会看到更改。这与共享缓存 (L2) 或持久性上下文 (L1) 无关。如果您还使用共享缓存,并直接更新数据库,那么您的共享缓存将过期。需要对对象进行refresh(),或者将其标记为无效,以便下次查询时刷新。

            代码必须遵循这样的方式。 分离 刷新 合并 冲洗

            【讨论】:

            • 但是如果你尝试刷新一个分离的实体,你会得到一个“java.lang.IllegalArgumentException: Entity not managed”。所以你必须分离、合并、刷新?
            猜你喜欢
            • 2011-01-05
            • 1970-01-01
            • 2013-02-11
            • 2012-04-19
            • 2011-07-14
            • 2017-08-17
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多