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

Jakarta ee 如何从CDI拦截器中清除EclipseLink查询结果缓存?,jakarta-ee,jpa,eclipselink,cdi,interceptor,Jakarta Ee,Jpa,Eclipselink,Cdi,Interceptor,我正在使用EclipseLink的查询结果缓存: @NamedQuery(name = "User.findAll", query = "SELECT s FROM ...", hints= { @QueryHint(name=QueryHints.QUERY_RESULTS_CACHE, value=HintValues.TRUE) ... 我首先使用名为“CacheManager”的无状态bean手动清除缓存,该bean具有

我正在使用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;
}
注意:我保留了上面的代码:拦截器注释接受一个类对象作为其参数,并且我使用该类对象查找其所有namedquerys的名称,其中包含一个QueryHint,指示它们已被缓存。这只是解释我如何找到要清除的命名查询

拦截器方法不起作用,我也不知道为什么我知道当我获得正确的日志消息时,方法
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=“…”)EntityManager em并清除缓存,而不使用CacheManager EJB


因此,回顾一下冗长的解释:我有两种方法调用使EclipseLink的查询结果缓存无效的同一个方法。我已经通过日志记录验证了这两种方法都能够使用相同的参数(namedquerynames)调用该方法。内联“after em.persist()”方法可以工作,但在拦截器中执行本质上完全相同的操作却不行。感觉上我正在用拦截器清除EclipseLink缓存的另一个实例,但我不知道这怎么可能。

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


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

您的EJB是无状态的还是有状态的?一切都是无状态的。可能是您正在清除会话bean的另一个实例。