gpt4 book ai didi

jakarta-ee - 如何从 CDI 拦截器清除 EclipseLink 查询结果缓存?

转载 作者:行者123 更新时间:2023-12-03 16:49:24 26 4
gpt4 key购买 nike

我正在使用 EclipseLink 的查询结果缓存:

 @NamedQuery(name = "User.findAll",
query = "SELECT s FROM ...",
hints= {
@QueryHint(name=QueryHints.QUERY_RESULTS_CACHE, value=HintValues.TRUE)
...

我首先使用名为“CacheManager”的无状态 bean 手动清除缓存,该 bean 具有以下方法:

public void invalidateCacheForQuery(String namedQueryName) {
log.info("CacheManagerService: clearing cache for named query " + namedQueryName);
((JpaCache) em.getEntityManagerFactory().getCache())
.clearQueryCache(namedQueryName);
}

每当有可能使查询结果过时的修改(添加/删除)时,我都会调用此方法。修改后直接调用,例如

em.merge(u);
cacheMan.invalidateCacheForQuery("..."); // for each cached query

(我在这里有点偷工减料,这是我所做工作的本质)。

上述解决方案运行良好 - 我有 JUnit 测试,如果未清除缓存,它们将失败,如果存在上述“invalidateCacheForQuery”调用,它们不会失败(如果不存在,则失败)。

然后我尝试通过定义一个拦截器让我的生活更轻松:

@EJB CacheManager cacheMan;

@AroundInvoke
public Object clearQueryCacheAfterwards(InvocationContext ctx)
throws Exception {

// this does something like em.persist that might make cached query results
// invalid:
final Object result = ctx.proceed();

// hera are calls cacheMan.invalidateCacheForQuery for all of the relevant named
// queries. Yes, this is done after ctx.proceed().

return result;
}

注意:我使上面的代码保持简洁:拦截器注释接受一个 Class 对象作为其参数,并且我使用该类对象来查找其所有具有 QueryHint 的 NamedQueries 名称,表明它们已被缓存。这只是为了解释我如何找到要清除的命名查询。

拦截器方法不起作用,我不知道为什么。 我知道方法 invalidateCacheForQuery(String namedQueryName) 也会在我收到正确的日志消息时使用拦截器方法(使用正确的命名查询名称)被调用。 我也收到日志消息形成拦截器。因此拦截器机制正在工作,例如这不是像 beans.xml 中缺少定义那样简单的问题。但是,我知道缓存清除不起作用,因为我的 JUnit 测试失败的方式与我根本不清除缓存时失败的方式相同。

查看日志,这些连续的行让我确定拦截器正在做它应该做的事情:

ClearQueryCacheInterceptor: clearing query cache for named query User.findAll 
CacheManagerService: clearing cache for named query User.findAll

我还尝试在拦截器中使用 @PersistenceContext(unitName="...") EntiytyManager em; 并在不使用 CacheManager EJB 的情况下通过它清除缓存。

所以回顾一下冗长的解释:我有两种方法调用相同的方法使 EclipseLink 的查询结果缓存无效。我已通过日志记录验证这两种方法都设法使用相同的参数(NamedQuery 名称)调用该方法。内联“在 em.persist() 之后”方式有效,但在拦截器中做基本上完全相同的事情却不行。感觉就像我正在使用拦截器清除 EclipseLink 缓存的另一个实例,但我不知道这怎么可能。

最佳答案

您的问题是您在使用拦截器方法时处理两个不同的 PersistenceContext。

看起来您的拦截器配置在实体级别上工作,它没有共享您的 EJB 容器的 PersistenceContext。尝试将拦截器移动到您的服务层(将其应用于持久化/修改数据的 EJB)。它不像您尝试的那样自动,但应该可以。

关于jakarta-ee - 如何从 CDI 拦截器清除 EclipseLink 查询结果缓存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15007922/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com