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
两个(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