【问题标题】:Create-or-Err with Objectify使用 Objectify 创建或错误
【发布时间】:2014-04-17 05:13:07
【问题描述】:

我开始使用 Google App Engine,并且正在使用 Objectify。如何在数据存储中创建根实体,但如果它已经存在则错误?我没有找到任何内置的东西(例如DatastoreService.put(),因此ofy().save() 将覆盖现有实体而不是错误)。我习惯的简单技术是在事务中执行此操作:

  1. 如果已经存在则错误
  2. 保存

但是,这不是幂等的;如果事务执行两次,它会在步骤 1 中出错。这是迄今为止我想出的最好的,不是在交易中:

  1. 如果已经存在则错误
  2. 保存
  3. 获取
  4. 如果不是我们刚刚创建的数据,那就错了

或者,如果我不介意两次成功保存相同数据的请求,我可以跳过初始查找:

  1. 获取
  2. 如果与我们即将创建的数据相同,则报告成功
  3. 错误,如果已经存在,但不是我们即将创建的数据
  4. 保存

这是可行的,但是要完成我认为非常简单的操作会有点笨重。有没有更好的办法?

【问题讨论】:

    标签: google-app-engine google-cloud-datastore objectify


    【解决方案1】:

    这应该保证一致的行为:

    final String id = // pick the unique id
    final long txnId = // pick a uuid, timestamp, or even just a random number
    
    ofy().transact(new VoidWork() {
        public void vrun() {
            Thing th = ofy().load().type(thing.class).id(id).now();
            if (th != null) {
                if (th.getTxnId() == txnId)
                    return;
                else
                    throw ThingAlreadyExistsException();
            }
    
            th = createThing(id, txnId);
            ofy().save().entity(th);
        }
    });
    

    【讨论】:

    • 当ThingAlreadyExistsException 实际上并不存在时,它不能抛出吗?如果 GAE 事务抛出异常,但它“已提交并最终将成功应用”,我的印象是 Objectify 将重新运行该事务。然后,我想,它会看到第一个事务的结果并抛出异常。
    • 我不这么认为。 Objectify 仅在遇到 ConcurrentModificationException 时重试,我认为在那种情况下保存不会“提交并最终成功应用”。
    • 来自the docs:“在事务已提交并最终将成功应用的情况下,您可能会收到DatastoreTimeoutException、ConcurrentModificationException 或DatastoreFailureException 异常。”
    • 好点。我已经更新了成功提交时解决 CME 的答案。我希望 Google 能详细说明可能导致这种情况的情况。
    • @stickfigure 天才!感谢您的编辑 - 现在我确信了。 :) 这比验证我写的所有数据是否相同要容易得多。
    猜你喜欢
    • 1970-01-01
    • 2018-05-31
    • 2018-06-25
    • 2014-02-21
    • 2017-06-01
    • 2017-04-01
    • 2012-02-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多