【问题标题】:JDO Query with cursors on GAE returns inconsistent results游标在 GAE 上的 JDO 查询返回不一致的结果
【发布时间】:2014-10-12 06:06:12
【问题描述】:

我正在对 GAE 服务器运行 GWT RPC 调用,使用 JDO 查询存储在数据存储中的文章对象,并且我正在使用游标对结果进行分页。

我发送一个初始 RPC 调用以开始分页,其中“范围”为 10 个结果。我将查询游标存储在内存缓存中,并在用户请求下一页的 10 个结果时检索它。实现这一点的代码如下所示。

范围始终相同,10 个结果。但是,一些后续的 RPC 调用会返回 2 个结果,或者 12 个结果。这是非常不一致的。这些调用有时也会返回重复的结果。

我已阅读此 Google 开发人员文档:https://developers.google.com/appengine/docs/java/datastore/queries#Java_Limitations_of_cursors。它提到:“对于在具有多个值的属性上使用不等式过滤器或排序顺序的查询,游标并不总是按预期工作。这种多值属性的重复数据删除逻辑在检索之间不会持续存在,可能导致多次返回相同的结果。”

正如您在代码中看到的,我正在对“日期”属性进行排序。该属性只有一个值。

你能让我看看我在这里做错了什么吗?谢谢。

这是在 GAE 服务器上执行 RPC 调用的代码:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.List;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.servlet.http.HttpSession;

import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.datanucleus.query.JDOCursorHelper;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

//...

private void getTagArticles(String tag, int range, boolean start) {

    PersistenceManager pm = PMF.getNonTxnPm();
    ArticleStreamItemSummaryDTO aDTO = null;
    ArticleStreamItem aDetached = null;
    summaryList = new ArrayList<ArticleStreamItemSummaryDTO>();
    String cursorString = null;
    session = getThreadLocalRequest().getSession();
    UserAccount currentUser = LoginHelper.getLoggedInUser(session, pm);
    String cursorID = currentUser.getId().toString() + tag;

    if (start) { // The start or restart of the query
        CacheSupport.cacheDelete(String.class.getName(), cursorID);
    }

    Object o = CacheSupport.cacheGet(String.class.getName(), cursorID);
    if (o != null && o instanceof String) {
        cursorString = (String) o;
    }

    Query q = null;
    try {
        q = pm.newQuery(ArticleStreamItem.class);

        if (cursorString != null) {
            Cursor cursor = Cursor.fromWebSafeString(cursorString);
            Map<String, Object> extensionMap = new HashMap<String, Object>();
            extensionMap.put(JDOCursorHelper.CURSOR_EXTENSION, cursor);
            q.setExtensions(extensionMap);
        }   
        q.setFilter("tag == tagParam");
        q.declareParameters("String tagParam");
        q.setOrdering("date desc");
        q.setRange(0, range);

        @SuppressWarnings("unchecked")
        List<ArticleStreamItem> articleStreamList = (List<ArticleStreamItem>) q.execute(tag);

        if (articleStreamList.iterator().hasNext()) {
            Cursor cursor = JDOCursorHelper.getCursor(articleStreamList);
            cursorString = cursor.toWebSafeString();
            CacheSupport.cacheDelete(String.class.getName(), cursorID);
            CacheSupport.cachePutExp(String.class.getName(), cursorID, cursorString, CACHE_EXPIR);
            for (ArticleStreamItem a : articleStreamList) {
                aDetached = pm.detachCopy(a);
                aDTO = aDetached.buildSummaryItem();
                summaryList.add(aDTO);
            }
        }
    }
    catch (Exception e) {
        // e.printStackTrace();
        logger.warning(e.getMessage());
    }
    finally {
        q.closeAll();
        pm.close();
    }
}

【问题讨论】:

    标签: java google-app-engine gwt jdo


    【解决方案1】:

    我在上述问题中提供的代码 sn-p 实际上运行良好。问题来自客户端。 RPC 调用有时彼此相隔几毫秒,这造成了我在返回的结果中看到的不一致行为。

    我将客户端代码更改为每 5 秒进行一次 RPC 调用,并且修复了它。

    【讨论】:

      猜你喜欢
      • 2016-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多