【问题标题】:Replace single entity in query cache from JPA/Hibernate/EclipseLink?从 JPA/Hibernate/EclipseLink 替换查询缓存中的单个实体?
【发布时间】:2014-04-06 00:54:12
【问题描述】:

我们需要缓存一个查询的结果;查询返回数据库的整个表。问题是数据库被其他应用程序从外部更改;使用更改的行的确切主键通知进行查询的 Java 应用程序。

是否可以只替换查询缓存中已更改的元素,而不是整个列表? 这是一级缓存(来自 EntityManager)二级缓存(来自 EntityManagerFactory)还是不同的缓存?

如果可以的话,这可以从 JPA 完成吗?

entityManager.refersh(entity);

或者这个查询缓存是二级 JPA 缓存:

entityManagerFactory.getCache().evict(cls, primaryKey);

还是只能通过 Hibernate/EclipseLink API 实现?

如果不可能,为了实现这一点,对所有元素调用entityManager.find() 会这样做吗?

我在Hibernate documentationEclipseLink documentation 中都没有找到任何有用的东西。 Hibernate 支持区域和仅刷新区域,但我们需要实体级别的刷新粒度。


稍后编辑以澄清我的发现。

按照@Chris 在评论中发布的链接,我发现我想要的实际上是supported by EclipseLink,但仅适用于 Oracle 数据库(可以为其他供应商实现自己的处理程序;但来自数据库的调用不是标准化并且因供应商而异)。我还没有发现 Hibernate 是否支持这一点。

无论如何,与 Spring Cache(基于 CocurrentMap)或基于自定义的缓存相比,来自 EclipseLink 的查询缓存的性能非常差,因此将继续使用 Spring Cache 或 Spring Jdbc 上的自定义缓存。

【问题讨论】:

    标签: java hibernate caching orm eclipselink


    【解决方案1】:

    EntityManager.refresh() 是您想要的 - 它从数据库中的内容刷新实体。如果您不在事务中,这也应该更新共享缓存中的实体,否则您可能需要使用 entityManagerFactory.getCache().evict(cls, primaryKey);以及清除二级共享缓存,以便以后也可以将其读入。

    【讨论】:

    • 那么查询缓存不是单独的缓存吗?
    • 查询缓存不是 JPA 的一部分,因此您必须针对您的提供者进行配置 - EclipseLink 的查询缓存默认情况下不启用,仅适用于查询的结果,不是返回的数据。因此,只要查询返回相同的实体,就应该从数据库中提取无效实体。
    • 对不起,意思是说文档暗示无效实体应该从数据库中刷新。如果更改影响将返回的查询结果(ID,而不是原始实体数据值),则需要使查询缓存无效。在 EclipseLink 2.5 中,这种情况发生了变化,使无效实体自动使使用这些实体的查询无效:java-persistence-performance.blogspot.com/2013/06/…
    • 感谢cmets的解答;从博客文章中,它提到这是可能的,但它只使用 Oracle 数据库自动执行;否则需要实现接口。你知道 Hibernate 是否也有这个功能吗?
    猜你喜欢
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 2019-07-19
    • 1970-01-01
    • 2023-03-24
    • 2013-10-18
    • 2014-02-06
    • 2022-10-18
    相关资源
    最近更新 更多