Appengine数据存储幻像实体 - 不一致状态?

时间:2010-06-13 17:56:29

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

在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){   继续;  }

有什么想法吗?

2 个答案:

答案 0 :(得分: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 /”

答案 1 :(得分:0)

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

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

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


好的,还有其他一些你可以尝试的东西

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

  2. 查看您是否可以使用该ID查询实体。像这样:

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

    然后尝试将其删除。

  3. 看看你是否可以获得实体的属性,也许这是你期望的另类。