Firebase:以原子方式创建/更新多个子节点

时间:2017-02-04 00:31:37

标签: android firebase transactions firebase-realtime-database

假设我有一个带有“用户”节点和“宠物”节点的项目。当用户获得宠物时,我想将宠物的密钥添加到用户的“宠物”节点,并将用户ID添加到宠物的“所有者”节点。

示例:

{
    "users":{
        "user1":{
            "pets":{
                "pet1":true,
                "pet3":true
            }
            ...
        }
    },
    "pets":{
        "pet1":{
            "owner":"user1",
            ...
        },
        ...
    }
}

我想确保两次更新都能成功阻止状态不一致。

我读到了如何使用Firebase事务here,但是当我尝试创建修改相关值的事务时(使用dbRef.runTransaction(...)),我收到此DatabaseError错误:< / p>

  

交易重试次数太多

当我在我修改的特定节点上调用runTransaction()时,事务似乎才有效(例如,调用

dbRef.child("users").child("user1").runTransaction(...));

然而,这对我没有帮助,因为我需要联系相关用户和宠物。 如何使此交易有效?

1 个答案:

答案 0 :(得分:5)

根据Firebase Docs,您不需要使用交易操作(我稍后会解释)。

为了在 ONE PACKET 的多个节点中保存数据,我建议您构建一个 Map&lt;&gt; 数组,其中表示路径, Value 表示您想要存储的内容。

假设“user1”刚刚成为“pet4”的所有者,并且您的dbRereference指向根目录:

FirebaseDatabase dbRef = FirebaseDatabase.getInstance().getReference();

Map<String, Object> update = new HashMap<>();
update.put("users/user1/pets/pet4", true);
update.put("pets/pet4/owner", "user4");

稍后您可以运行 .updateChildren(Map&lt;,&gt;)并附加一个监听器。

dbRef.updateChildren(update).addOnCompleteListener(new OnCompleteListener<Void>() {
    @Override
    public void onComplete(@NonNull Task<Void> task) {
        if (task.isSuccessful())
            Log.d("Success!");
        else
            Log.d("Failure");
    }
});

通过这种方式,如果发生故障,您的数据库将根本不会被更改。

“交易”是Firebase为不同操作提供的术语,我认为这是导致您混淆的原因:在处理可能被并发修改(例如增量计数器)损坏的数据时使用它。如需进一步阅读,请打开开头附带的链接。