我正在运行对GAE服务器的GWT RPC调用,查询使用JDO存储在数据存储区中的文章对象,并且我使用游标对结果进行分页。
我发送一个初始RPC调用,以10个结果的“范围”开始分页。我将查询光标存储在memcache中,并在用户请求下一页10个结果时检索它。实现此目的的代码如下所示。
范围总是相同的,10个结果。但是,某些后续RPC调用返回2个结果,或12个结果。这是非常不一致的。调用有时也会返回重复的结果。
我已阅读此Google开发人员文档:https://developers.google.com/appengine/docs/java/datastore/queries#Java_Limitations_of_cursors。它提到:“游标并不总是按预期工作,使用不等式过滤器或具有多个值的属性上的排序顺序。这种多值属性的重复数据删除逻辑在检索之间不会持续存在,可能导致相同的结果不止一次返回。“
正如您在代码中看到的那样,我正在对“date”属性进行排序。此属性只有一个值。
你能让我看看我在这里做错了吗?感谢。这是在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();
}
}
答案 0 :(得分:1)
我在上面的问题中提供的代码段实际上效果很好。问题来自客户端。 RPC调用有时会相隔几毫秒,这就是我在返回的结果中看到的不一致行为。
我更改了客户端代码,每5秒进行一次RPC调用,然后修复它。