2

在过去可以正常工作的 java appengine 代码上出现一个奇怪的错误(除了数据存储中的数据没有任何变化)。

我正在尝试迭代查询结果并更改实体的一些属性。该查询确实返回了一组结果,但是,当我尝试访问列表中的第一个结果时,它会在尝试访问其任何属性(但它的键)时引发异常。这是一个例外:

org.datanucleus.state.JDOStateManagerImpl isLoaded: Exception thrown by StateManager.isLoaded
Could not retrieve entity of kind OnTheCan with key OnTheCan(3204258)
org.datanucleus.exceptions.NucleusObjectNotFoundException: Could not retrieve entity of kind OnTheCan with key OnTheCan(3204258)
 at org.datanucleus.store.appengine.DatastoreExceptionTranslator.wrapEntityNotFoundException(DatastoreExceptionTranslator.java:60)

这是我的代码:

PersistenceManager pm = PMF.get().getPersistenceManager();
Query query = null;
List<OnTheCan> cans;
query = pm.newQuery("SELECT this FROM " + OnTheCan.class.getName() + " WHERE open == true ORDER BY onTheCanId ASC");
query.setRange(0, num);
cans = (List<OnTheCan>) query.execute();
for (OnTheCan c : cans)
{
 System.err.println(c.getOnTheCanId()); // this works fine! getting the key works
 c.setOpen(false); // failure here with the above exception
 c.setAutoClosed(true);
 c.setEndTime(new Date(c.getStartTime().getTime() + 600000/*10*60*1000*/));
}
pm.close();

代码在尝试执行 c.setOpen(false) 时引发异常 - 这是我第一次访问或设置不是键的属性。因此,我的数据存储中似乎有一个虚拟实体,密钥为 3204258。这个实体并不真正存在(从管理控制台查询数据存储),但由于某种原因,它被查询返回。我的数据存储可能处于不一致的状态吗?

我通过将它作为我的 for 循环中的第一行来管理以下解决方法。显然是一个丑陋的黑客:

if (c.getOnTheCanId() == 3204258) { 继续; }

有任何想法吗?

4

2 回答 2

2

我认为您的索引之一可能已损坏。您可能需要检查http://appengine.google.com/datastore/indexes?&app_id= {your_app_id} 并查看其中是否有任何报告错误。如果是这样,它们可能需要重建。

这可能会有所帮助(取自http://osdir.com/ml/GoogleAppEngine/2009-05/msg00904.html):

要清理并重建索引:

  1. 创建 index.yaml 规范的备份。
  2. 从您的管理控制台确定状态为 ERROR 的索引:http ://appengine.google.com/datastore/indexes? &app_id= {app_id}
  3. 从 index.yaml 文件中删除 ERROR 中的索引定义。
  4. 运行“appcfg.py Vacuum_indexes your_app_dir/”
  5. 等到 ERROR 索引不再出现在您的管理控制台中。
  6. 将 index.yaml 文件的修改版本替换为原始版本。
  7. 运行“appcfg.py update_indexes your_app_dir/”
于 2010-06-22T09:39:42.817 回答
0

这可能是 Andrei 所说的索引损坏,但如果您不愿意重建所有索引,请尝试仅删除该实体。像这样的东西:

  if (c.getOnTheCanId() == 3204258) {
            //continue;
            pm.deletePersistent(c); 
        }

在没有 if 子句的情况下再次测试它之后......


好的,您可以尝试其他一些事情

  1. 检查您的自动和自定义索引(index.yaml 文件)。看看您是否不再使用某些查询,但无论如何您都已将其编入索引。也许这就是为什么你有错误的索引表。

  2. 看看您是否可以查询具有该 ID 的实体。像这样:

    密钥 k = KeyFactory.createKey(OnTheCan.class.getSimpleName(),3204258); pm.getObjectById(OnTheCan.class, k);

    然后尝试删除它。

  3. 看看你是否可以获得实体的属性,也许它是你所期望的不同类型。

于 2010-06-22T12:19:48.890 回答