GAE / J-JDO按实体类型选择返回过期结果

时间:2013-03-20 16:59:14

标签: google-app-engine google-cloud-datastore jdo datanucleus

暂时调查问题。所以问社区。 我的目标是获取特定类型的所有实体,它们都需要是最新的。 (暂不考虑任何事务隔离 - 可以是脏读)

我使用GAE / J-JDO(使用tx.begin()只是一个预防措施):

    PersistenceManager pm = PMF.get().getPersistenceManager();
    Transaction tx = pm.currentTransaction();
    Query q = pm.newQuery(TokenJdo.class);
    List<TokenJdo> tokenList = (List<TokenJdo>) q.execute();
    Collection<TokenJdo> res = Collections.unmodifiableCollection(tokenList);
    tx.commit();
    pm.close();
    for (TokenJdo t : tokenList) {
        log.info(t.getToken() + " - " + t.getCounter());
    }

这样做会给我过时的实体(我请求列表,转到AppEngine控制台并修改一个实体,再次请求列表)。 所以我直接使用DatastoreService编写了以下调试代码。

    DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
    com.google.appengine.api.datastore.Query gaeQuery = new com.google.appengine.api.datastore.Query(TokenJdo.class.getSimpleName());
    PreparedQuery pq = ds.prepare(gaeQuery);
    List<Entity> list = pq.asList(FetchOptions.Builder.withDefaults());
    for (Entity i : list) {
        log.info(i.getKey() + " - " + i.getProperties());
    }

在一个请求中执行两段代码会得到以下输出,并显示与DatastoreService返回的内容相比,JDO中的数据已过时:

I 2013-03-20 12:31:16.950 com.serverside.bl.TokenProviderJdo getAll: dummy - -999
I 2013-03-20 12:31:16.950 com.serverside.bl.TokenProviderJdo getAll: asd - 0
I 2013-03-20 12:31:16.951 com.serverside.bl.TokenProviderJdo getAll: dummy-aaa - -111
I 2013-03-20 12:31:16.957 com.serverside.bl.TokenProviderJdo logDSEntities: TokenJdo(7003) - {token=dummy, counter=-999}
I 2013-03-20 12:31:16.957 com.serverside.bl.TokenProviderJdo logDSEntities: TokenJdo(12001) - {token=asd, counter=0}
I 2013-03-20 12:31:16.957 com.serverside.bl.TokenProviderJdo logDSEntities: TokenJdo(13001) - {token=dummy-aaa, counter=-222}

显然(或者我看来)JDO使用某种内部缓存(L1或L2,虽然我没有明确启用任何内容)。如何让JDO做一个“干净”的阅读?

1 个答案:

答案 0 :(得分:0)

要阻止datanucleus缓存任何内容,您应该禁用两个缓存级别:

datanucleus.cache.level1.type=none
datanucleus.cache.level2.mode=none

或者您可以按Query或按PersistenceManager停用缓存,只需使用QueryPersistenceManager方法设置提及的密钥。

另一方面,在查找对象后需要使用它们时,应该分离对象。我不太确定这个的技术原因,因为PersistenceManager应该在从使用它的方法返回之前关闭,或者我学会了,但是在禁用所有缓存之后,你必须完全分离查找的对象在使用之前。