【发布时间】: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