Eclipse Connect Cache未在缓存协调中正确刷新

时间:2014-07-04 15:09:54

标签: eclipselink

我尝试使用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;
}

2 个答案:

答案 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提供了几种处理陈旧数据的机制,包括:

  • 刷新
  • 失效
  • 乐观锁定
  • 缓存协调