Room数据库事务回滚

5

使用Room Database时,我正在从不同的DAO执行多个DELETE + INSERT查询。

我正在使用事务如下:

myDb.runInTransaction(new Runnable() {
     @Override
     public void run() {
     }
});

如果出现任何失败情况,是否有一种方法可以进行回滚 (ROLLBACK)?

后续编辑: 使用这种模式似乎可以起到作用:

myDb.beginTransaction();
if(success){
 myDb.setTransactionSuccessful(); -> commit
}
myDb.endTransaction();

我显然回答了一个非常相似的问题。如果你有多个语句,那么有一种回滚的方法,但你需要使用不同的模式。 - Tim Biegeleisen
我的问题是关于Room持久性库的。但实际上,使用不同的事务模式似乎可以解决这个问题。myDb.beginTransaction(); 然后如果事务成功,运行 myDb.setTransactionSuccessful(); 最后运行 myDb.endTransaction(); - Alex Busuioc
你如何确定isSuccess,你将读取事务中每个查询的输出吗?@AlexBusuioc - lib4backer
2个回答

2
如果发生异常,交易将不会被设置为成功,这意味着在事务结束时将被回滚。以下是“runInTransaction()”的代码:(查看代码)
public void runInTransaction(Runnable body) {
    beginTransaction();
    try {
        body.run();
        setTransactionSuccessful();
    } finally {
        endTransaction();
    }
}

因此,您可以创建类似以下内容的东西:
try {
    myDb.runInTransaction(new Runnable() {
        @Override
        public void run() {
            // DELETE
            if (failed) {
                throw new Exception("failed"); // ROLLBACK
            }
            // INSERT
        }
    });
} catch (Exception ex) {
    // Error handling
}

Runnable代码被同步调用。

如果代码使用lambda而不是Runnable匿名类,它看起来会更加清晰。 :)


你能否在Runnable的run()方法内抛出异常? - Alex Busuioc
是的。请注意,在这种情况下,“Runnable”不在“Thread”中(这是一种常见情况)。因此,它是同步运行的,这就是为什么您可以捕获“Exception”的原因。 - Xavier Rubio Jansana
@XavierRubioJansana 如果出现“失败”,这里的“失败”是指异常还是执行查询返回的结果?如果我捕获异常并重新抛出以便UI反映出发生了错误,那么事务是否仍会回滚? - user2234
1
嗨@user12865。我所说的失败是指您可能需要的任何条件(查询返回的结果可能会做到这一点)。在异常情况下,如果您需要在重新抛出之前进行一些处理(例如清理某些内容,甚至记录异常以进行调试),则可以捕获它。如果那是您唯一要做的事情,您实际上不需要捕获和重新抛出,因为原始异常将回滚事务(如果未缓存)。 - Xavier Rubio Jansana
1
@XavierRubioJansana 感谢您澄清了混淆的问题。 - user2234
显示剩余3条评论

1
希望我的回答能帮到你,因为我不知道你想要做的方法的其他信息。来自Android开发者文档。
 @Dao
public abstract class ProductDao{
    @Insert
     public abstract void insert(Product product);
     @Delete
     public abstract void delete(Product product);
     @Transaction
     public void insertAndDeleteInTransaction(Product newProduct, Product oldProduct) {
         // Anything inside this method runs in a single transaction.
         insert(newProduct);
         delete(oldProduct);
     } 
  }

在方法中使用@Transaction注解,以表明其中进行的所有更改都将被包装在一个事务中。


不,那是错误的。Room 不管理事务。它只确保所有内容在一个事务中运行。您需要自己管理错误事务。 - Lebron11

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接