如何使用Objectify事务以原子方式更新多个实体

时间:2018-01-09 07:07:00

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

我使用google-app-engine作为我的REST后端和google-datastore作为数据库。我通过objectify访问数据存储区。

我有一个API调用,我想要更新多个实体(让我们说3个实体)。

我的要求是要么全部更新,要么都不应更新。我希望在可能的情况下保证这一点,包括运行代码的实例崩溃/发生故障的错误情况。

即使我在交易中进行所有更新,如何确保原子性

<update id="update"
    parameterType="com.MyClass">
    UPDATE
        Board SET Status = 1
    <where>
        <if test="A != null and A.length() > 0">AND A = ${A}</if>
    </where>
</update>

让我们说上面所有上面的save()都发生在事务中,现在如果运行此代码的实例在&#34; thing1&#34;之后崩溃了。保存,我会有一个实体更新的情况和其他我想避免的实体。

我查看了交易的客观化文档:https://github.com/objectify/objectify/wiki/Transactions#basic-transactions,但无法找到任何此类示例或说明

我还查看了数据存储文档:https://cloud.google.com/datastore/docs/concepts/transactions

我从未直接使用数据存储,因此我对其API不是很熟悉,但在上面的链接中,他们给出了一个将资金从一个帐户转移到另一个帐户的示例,其中从描述看起来两个实体的更新是原子地发生(否则它不会处理运行代码的实例在从一个帐户扣除金额并将其贷记给另一个帐户之后崩溃的极端情况)。我的理解是否正确?

基本上我的问题是:

  1. 是否有一种方式可以客观地更新多个实体(处理运行代码崩溃的实例的极端情况)?如果是,那么如何?
  2. 如果没有,那么有哪些替代方案?
  3. 是否可以直接使用数据存储区API?我在上面分享的有关转移资金和原子更新示例的链接中是否提供了该示例?如果我在数据存储区的put()API中提供多个实体 - 在所有场景(包括实例崩溃)中是否保证所有更新都不会发生?
  4. 有一种API可以实现批量更新实体:

    OFY()保存()实体(entityList)。现在();

  5. 但是根据我的理解,此API不保证是原子的,因此我不能将它用于我的情况。我的理解是否正确?

1 个答案:

答案 0 :(得分:1)

基本上 Objectify 允许您访问Cloud Datastore功能。这意味着为了做你想做的事情(原子保存或更新),你必须在事务中更新/保存数据,因为(来自here):

  

交易是一组或一组Google Cloud Datoreore操作   更多实体。 每个事务都保证是原子的,哪个   意味着永远不会部分应用交易。全部或全部   应用事务中的操作,或者都不应用   应用

  1. 关于你的第一个问题:
  2. 您应该使用交易方法,就像在此example中一样:

    import static com.googlecode.objectify.ObjectifyService.ofy;
    import com.googlecode.objectify.Work;
    
    // If you don't need to return a value, you can use VoidWork
    Thing th = ofy().transact(new Work<Thing>() {
        public Thing run() {
            Thing thing = ofy().load().key(thingKey).now();
            thing.modify();
            ofy().save().entity(thing);
            return thing;
        }
    });
    

    Objectify interface的JavaDoc中声明:

      

    您可以通过调用 Objectify.transact()或来运行交易   的 Objectify.transactNew();

    1. 现在你的第三个问题:
    2. 您可以使用数据存储API,在this tutorial中有一个事务示例:

      boolean markDone(long id) {
        Transaction transaction = datastore.newTransaction();
        try {
          Entity task = transaction.get(keyFactory.newKey(id));
          if (task != null) {
            transaction.put(Entity.newBuilder(task).set("done", true).build());
          }
          transaction.commit();
          return task != null;
        } finally {
          if (transaction.isActive()) {
            transaction.rollback();
          }
        }
      }
      
      1. 第四个问题:
      2. 确保在事务中执行该行代码。希望这有帮助