Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当SingleValueEvent或Transaction的嵌套ValueEventListener失败时,如何回滚到Firebase RealtimeDB for Android中的上一个状态?_Java_Android_Firebase_Firebase Realtime Database - Fatal编程技术网

Java 当SingleValueEvent或Transaction的嵌套ValueEventListener失败时,如何回滚到Firebase RealtimeDB for Android中的上一个状态?

Java 当SingleValueEvent或Transaction的嵌套ValueEventListener失败时,如何回滚到Firebase RealtimeDB for Android中的上一个状态?,java,android,firebase,firebase-realtime-database,Java,Android,Firebase,Firebase Realtime Database,我正在开发一个基于Java和Firebase的本机Android应用程序,它需要根据特定操作多次写入(使用SingleValueEventListener或事务)不同的实时DB引用。 有点像: 用户单击一个按钮 在DB ref 1的SingleValueEventListener1/Transaction1中,DB reference 1得到更新 成功更新DB ref 1后,在SingleValueEventListener1/Transaction1中嵌套的另一个SingleValueEven

我正在开发一个基于Java和
Firebase
的本机Android应用程序,它需要根据特定操作多次写入(使用
SingleValueEventListener
或事务)不同的实时DB引用。 有点像:

  • 用户单击一个按钮
  • 在DB ref 1的SingleValueEventListener1/Transaction1中,DB reference 1得到更新
  • 成功更新DB ref 1后,在SingleValueEventListener1/Transaction1中嵌套的另一个SingleValueEventListener2/Transaction2中,DB ref 2开始更新。
    ……等等
  • 我需要什么?

    仅在我尝试更新的第一个位置成功后,才更新第二个DB位置。这些位置便于并发更新

    初步研究:

    我看过关于DB回滚、并发更新、多位置更新、数据库规则和安全性的各种帖子和堆栈溢出问题,但没有一个对我的事业有所帮助

    我看过哪些资源?

    ,

    有什么问题吗?

    在更新参考资料时没有问题。问题在于,如果DB reference 1更新成功,而DB reference 2更新失败,那么我没有选项将Ref 1回滚到以前的状态

    是否需要这种方法?

    就我而言,不幸的是,是的

    解决这个问题的一些方法是什么?

  • 我可以存储ref1的先前状态,如果ref2的更新失败,我可以重写ref1的先前状态。 但是这些位置支持并发更新,当我回滚到以前的状态时,以前的状态也可能已经更新了。以前的数据可能会过时,使用该数据覆盖ref可能会导致数据丢失。解决所有这些问题需要代码中不必要的复杂性,而这些复杂性可能根本不能保证解决问题

  • 事务肯定会尝试更新Ref 2,直到成功,但直到某个时间,并且可能是由于网络连接丢失而导致在第二个位置写入失败,这部分解释了我的担忧

  • 另一个选项是更改DB设计并将所有多个DB引用移动到一个位置,这样,如果位置更新失败,则不会根据Firebase进行任何更改。然而,我设计数据库的方式似乎还不错。事实上,为了方便解决这个问题,如果我改变我的数据库结构,并将数据转移到一个位置,我的情况将是完全错误的。为了用类似的情况来解释这一点,例如,在StackOverflow中,如果我对一个答案投了赞成票,那么回答者的声誉会发生变化,答案的状态会随着所涉及的人和投票数的变化而变化,投赞成票者的活动也会发生变化,也可能是他的声誉。现在,无法将上述所有DB REF合并为一个DB REF

  • 该问题与SingleValueEventListeners或事务无关

    出现问题的案例的简单代码示例?

    为了简单起见,下面演示了两级深层嵌套EventListeners(同样适用于事务)

    ValueEventListener outerListener = new ValueEventListener() {
      @Override
      public void onDataChange(DataSnapshot dataSnapshot) {
        if (dataSnapshot.exists()) {
        //do something
        //update DBRefOne
        DBRefOne.updateChildren(newOuterValue, new DatabaseReference.CompletionListener() {
          @Override
          public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
            ValueEventListener innerListener = new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
              if (dataSnapshot.exists()) {
              //do something
              //update DBRefTwo
              DBRefTwo.updateChildren(newInnerValue);
              }
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
           // log error
          }
        };
        DBRefTwo.addListenerForSingleValueEvent(innerListener);
       }
     });
    }
    }
      @Override
      public void onCancelled(DatabaseError databaseError) {
      // log error
      }
    };
    DBRefOne.addListenerForSingleValueEvent(outerListener);
    

    这对我来说是一个不平凡但棘手的问题,需要解决,因为大多数应用程序都是以其他方式完成的。我愿意根据你的建议返工。请随时提出建议,任何帮助都是非常谦虚和感激的。

    有两种方法可以事务性地更新数据:

  • 使用事务
  • 使用多位置更新
  • 没有隐藏的第三种方法,因此如果您想以事务方式更新数据,您必须使用其中一种方法

    如果写入的值不是基于当前值,则应使用多位置更新,因为它具有更好的性能特征。有关这方面的更多信息,请阅读以下博文:


    如果您写入的值基于当前值,则需要使用事务。在这种情况下,确保您正在编写的数据在JSON中彼此接近是很重要的,因为您在更新位置的顶部有效地放置了一个(乐观的)锁。

    我在下面的选项中给出了一个快速答案。我很感激你在你的问题上做得很透彻,但这使得解析工作相当繁重。我建议编辑时只把重点放在图片上。例如,在您当前的代码片段中,我们不知道
    DBRefOne
    DBRefTwo
    之间有何关联,也不知道
    newOuterValue
    newInnerValue
    是基于什么。感谢您的回复。我会把你的建议放在手边,以备将来发布。但是,根据您对事务的响应(因为我的值基于当前值),我仍然要问您,当外部事务成功时会发生什么,一旦完成,嵌套的内部事务开始执行,但失败了-如何恢复外部事务的上一个值,存储它不是一个选项,因为届时它可能会更新?事务尝试了很多次,但在一点之后停止。这是一个边缘的情况,但一个有效的。您对此有何看法,请随时告诉我。没有事务嵌套。您必须在单个事务中进行更新,这意味着您必须在JSON中的最低级别运行该事务,您可以在该级别上获得两个值。树中越高,即事务执行情况越差。