JPQL 无法阻止 JPQL 查询的缓存

JPQL can not prevent cache for JPQL query

两个(JSF + JPA + EclipseLink + MySQL)应用程序共享同一个数据库。一个应用程序运行计划任务,而另一个应用程序为计划创建任务。第一个应用程序创建的任务由第二个应用程序中的查询收集,没有任何问题。第二个应用程序更新任务中的字段,但是第二个应用程序所做的更改在 JPQL 查询时不会刷新。

我已将 QueryHints.CACHE_USAGE 添加为 CacheUsage.DoNotCheckCache,但最新的更新并未反映在查询结果中。

代码如下。

如何通过 JPQL 查询对数据库进行最新更新?

public List<T> findByJpql(String jpql, Map<String, Object> parameters, boolean withoutCache) {
    TypedQuery<T> qry = getEntityManager().createQuery(jpql, entityClass);
    Set s = parameters.entrySet();
    Iterator it = s.iterator();
    while (it.hasNext()) {
        Map.Entry m = (Map.Entry) it.next();
        String pPara = (String) m.getKey();
        if (m.getValue() instanceof Date) {
            Date pVal = (Date) m.getValue();
            qry.setParameter(pPara, pVal, TemporalType.DATE);
        } else {
            Object pVal = (Object) m.getValue();
            qry.setParameter(pPara, pVal);
        }
    }
    if(withoutCache){
        qry.setHint(QueryHints.CACHE_USAGE, CacheUsage.DoNotCheckCache);
    }
    return qry.getResultList();
}

通过添加以下行使实体不依赖于缓存。

@Cache(
  type=CacheType.NONE, // Cache nothing
  expiry=0,
  alwaysRefresh=true
)

CacheUsage 设置会影响 EclipseLink 可以使用内存中的内容进行查询的内容,但不会影响它进入数据库获取结果后发生的情况。

您似乎不想直接避开缓存,但我想刷新它以便可以看到最新的更改。当涉及多个应用程序和缓存级别时,这是一种非常常见的情况,因此您可能需要研究许多不同的解决方案,例如手动失效,或者即使两个应用程序都基于 JPA,缓存协调(因此一个应用程序可以发送一个甚至对另一个无效)。或者您可以使用 "eclipselink.refresh" 查询提示对特定查询进行控制,这将强制查询使用从数据库返回的内容重新加载缓存对象中的数据。请注意它,就像在本地 EntityManager 中使用一样,查询返回的任何修改的实体也将被刷新并且更改丢失

缓存参考:

https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Caching

https://www.eclipse.org/eclipselink/documentation/2.6/concepts/cache010.htm