我尝试使用eclipselink构建缓存协调,这就是问题所在。 db中有一个表,其中包含 NAME 和 CHECK_TIME 列。我的第一个应用程序有FULL缓存,而 getAll()它在开始时从DB加载所有值到缓存。之后,将get("name_"+i)
循环中的对象打印为[name_1,2014-07-04 00:00:00],[name_2,2014-07-04 00:00:00]
,依此类推。
由于缓存协调,第二个应用程序使用相同的缓存,并使用 merge()更新CHECK_TIME值,我可以在db中看到这些新值。因此,第二个应用程序每秒检查一行并更新 CHECK_TIME 列。
第二个应用程序启动后,第一个应用程序打印旧的CHECK_TIME值甚至rmi日志表示对象已合并。所以我认为缓存协调起初并不起作用,但是,如果我尝试在第二个应用程序中使用 persist()(如[new_name_1,2014-07-04 16:43:32]
创建一个新对象,那么第一个应用程序将其打印到屏幕上立即意味着缓存正确刷新。
你知道为什么get('name_'+i)
返回总是旧的值甚至缓存刷新?这就像eclipselink中有一个二级缓存。
的persistence.xml
<property name="eclipselink.cache.coordination.protocol" value="rmi" />
<property name="eclipselink.cache.coordination.naming-service" value="rmi" />
<property name="eclipselink.cache.coordination.rmi.url" value="rmi://$HOST:1090" />
Subsciber.java
@NamedQueries({
@NamedQuery(name = "get", query = "select b from Subscriber b where b.name = :name ", hints = {
@QueryHint(name = QueryHints.QUERY_TYPE, value = QueryType.ReadObject),
@QueryHint(name = QueryHints.CACHE_USAGE, value = CacheUsage.CheckCacheOnly)}),
@NamedQuery(name = "getAll", query = "select b from Subscriber b ", hints = {
@QueryHint(name = QueryHints.QUERY_TYPE, value = QueryType.ReadAll),
@QueryHint(name = QueryHints.CACHE_USAGE, value = CacheUsage.DoNotCheckCache)})})
@Cache(type = CacheType.FULL, coordinationType = CacheCoordinationType.SEND_NEW_OBJECTS_WITH_CHANGES)
修改
private SubscriberIdentity get(String name) {
SubscriberIdentity result = null;
try {
//entityManager is global
Query query = entityManager.createNamedQuery("get");
query.setParameter("name", name);
result = (SubscriberIdentity) query.getSingleResult();
} catch (Exception e) {
if (e.getCause() instanceof NoResultException || e instanceof NoResultException) {
//TODO
}
}
return result;
}
答案 0 :(得分:1)
@Chris在评论方面有很大的帮助,我知道问题是使用静态entityManager对象,因为它使用自己的缓存而不是在第二次调用 get(name_1)的情况下检查共享缓存。所以我改变了
Query query = entityManager.createNamedQuery("get");
部分为
EntityManager em = new EntityManager();
Query query = em.createNamedQuery("get");
在getter和缓存协调中,也适用于UPDATE案例。
答案 1 :(得分:0)
正如@Chris所说,您还可以查看文档EL Cache:
默认情况下,EclipseLink使用缓存a的共享对象缓存 持久性单元读取和保留的所有对象的子集。该 EclipseLink共享缓存与本地EntityManager缓存不同。 共享缓存在持久性单元的持续时间内存在 (EntityManagerFactory或服务器)并由所有EntityManagers共享 和持久性单元的用户。本地EntityManager缓存是 不共享,仅在EntityManager或者持续时间内存在 事务。
共享缓存的限制是,如果直接通过JDBC或其他应用程序或服务器更改数据库,则共享缓存中的对象将过时。
EclipseLink提供了几种处理陈旧数据的机制,包括: