0

我有这个代码在没有 HR 的情况下工作得很好:

protected Entity createEntity(Key key, Map<String, Object> props){
    Entity result = null;
    try {
        Entity e = new Entity(key);
        Iterator it = props.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, Object> entry = (Map.Entry<String, Object>) it.next();
            String propName = entry.getKey();
            Object propValue = entry.getValue(); 
            setProperty(e, propName, propValue);
        }
        key = _ds.put(e);
        if (key != null)
            result = _ds.get(key);
    } catch (EntityNotFoundException e1) {
    }
    return result;
}

这只是一个简单的方法,它的功能是创建一个新的Entityout aa given key,否则返回 NULL 。如果没有 JUnit 中的 HR 配置,这可以正常工作,但是当我配置它时,我总是收到一个错误,在哪里_ds.get(key)找不到键抛出:

EntityNotFoundException: No entity was found matching the key:

具体做的时候:

while(it.hasNext()){
   // stuff
   createEntity(key, map); 
   // stuff
}

我认为我的代码中的问题是它试图过早地获取实体。如果是这样的话,我怎么能不诉诸Memcache或类似的东西来处理这个问题。

更新:

createEntity事务中执行时,它会失败。但是,如果我在交易之外删除它,如果失败得很惨。我需要能够在事务中运行,因为我的更高级别的 API 将许多需要作为一个组存在的对象。

更新:

我听从了 Strom 的建议,但是我发现了一个奇怪的副作用,而不是_ds.get(key)对方法进行操作,这让我PreparedQuery countEntities失败了。如果添加一个_ds.get(key)甚至我不做任何事情或保存Entity从那个得到的countEntities回报返回预期的计数。这是为什么?

4

2 回答 2

1

You try to create a new entity and then read back that entity within the same transaction? Can't be done.

Queries and gets inside transactions see a single, consistent snapshot of the datastore that lasts for the duration of the transaction. 1

In a transaction, all reads reflect the current, consistent state of the Datastore at the time the transaction started. This does not include previous puts and deletes inside the transaction. Queries and gets inside a transaction are guaranteed to see a single, consistent snapshot of the Datastore as of the beginning of the transaction. 2

This consistent snapshot view also extends to reads after writes inside transactions. Unlike with most databases, queries and gets inside a Datastore transaction do not see the results of previous writes inside that transaction. Specifically, if an entity is modified or deleted within a transaction, a query or get returns the original version of the entity as of the beginning of the transaction, or nothing if the entity did not exist then. 2

PS. Your assumption is worng, it's impossible to fetch an entity by key "too soon". Fetches by key are strongly consistent.

Also, why do you need to retrieve the entity again anyway? You just put it in the datastore yourself, so you already have its contents.

So change this part:

key = _ds.put(e);
    if (key != null)
        result = _ds.get(key);

To this:

key = _ds.put(e);
    if (key != null)
        result = e; // key.equals(e.getKey()) == true
于 2013-04-10T11:47:00.013 回答
0

欢迎来到 GAE 环境,在你放弃之前尝试多读一遍:

 int counter = 0;
 while (counter < NUMBER_OF_TRIES){
  try {

   //calling storage or any other non-reliable thing
   if(success) {break;} //escape away if success

   } catch(EntityNotFoundException e){
     //log exception
     counter++;
   }
 }

谷歌文档中的重要说明:“您可以写入同一实体组的速率限制为每秒 1 次写入实体组。”

来源:https ://developers.google.com/appengine/docs/java/gettingstarted/usingdatastore

于 2013-04-10T10:10:20.713 回答