房间事务回滚

Room Transaction rollback

根据room documentation事务回滚事务中的每个查询,以防发生错误。

所以我在这里测试了回滚:

@Transaction
public Completable updateTable1(Table table1) {
    return Completable.fromAction(
            () -> 
                table1.setNotice("why am i updateed????");
                synchronousUpdate(table1);
                table1.setForeignKeyId(90); //some random foreign key which does not exsist so it throws an exception
                synchronousUpdate(table1);
            }
    );
}

@Update
void synchronousUpdate(T obj);

即使第二次更新抛出错误,我的表 1 仍会更新。

可能是什么原因?我是因为我 return 是一个可完成的而不是像 void?

这样的同步 return 值

文档说

The transaction will be marked as successful unless an exception is thrown in the method body.

它实际上并没有说 异常将被管理,尽管 ROLLBACK 将被跳过,即跳过 setTransactionSuccessful 和 endTransaction被执行。如果您查看生成的代码,例如编码方法是:-

@Transaction
public boolean update4(Bookmark b1, Bookmark b2) {
    if (update(b1) > 0) {
        if (update(b2) < 1) {
            abort(b1);
            return false;
        }
    } else {
            abort(b1);
        return false;
    }
    return true;
}

房间生成的代码是:-

  @Override
  public boolean update4(final Bookmark b1, final Bookmark b2) {
    __db.beginTransaction();
    try {
      boolean _result = AllDao_Impl.super.update4(b1, b2);
      __db.setTransactionSuccessful();
      return _result;
    } finally {
      __db.endTransaction();
    }
  }

没有catch,需要相应处理异常

考虑以下(给出的先前答案的修改版本):-

    b1.setPostUrl("YetAnotherURL");
    b5.setPostTitle("P5");
    b5.setPostUrl("U5");
    try {
        dao.update4(b1, b5);
    }
    catch (Exception e) {
        e.printStackTrace();
    }
    logInfo("-D1");
    dao.update4(b1,b5);
    logInfo("-D2");

基本相同的更新,不会更新 (return 0) 因为 id 不存在,运行 两次。不同之处在于第一个在 try/catch 块中。

日志结果:-

2021-07-09 12:04:38.344 W/System.err: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: mylist_data.ID (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)
2021-07-09 12:04:38.348 W/System.err:     at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
2021-07-09 12:04:38.349 W/System.err:     at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:796)
2021-07-09 12:04:38.349 W/System.err:     at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
2021-07-09 12:04:38.349 W/System.err:     at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
2021-07-09 12:04:38.349 W/System.err:     at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:51)
2021-07-09 12:04:38.349 W/System.err:     at androidx.room.EntityInsertionAdapter.insertAndReturnId(EntityInsertionAdapter.java:114)
2021-07-09 12:04:38.349 W/System.err:     at a.a.so67958704javaroomconvertexistingdb.AllDao_Impl.abort(AllDao_Impl.java:133)
2021-07-09 12:04:38.349 W/System.err:     at a.a.so67958704javaroomconvertexistingdb.AllDao.update4(AllDao.java:40)
2021-07-09 12:04:38.350 W/System.err:     at a.a.so67958704javaroomconvertexistingdb.AllDao_Impl.access[=13=]1(AllDao_Impl.java:22)
2021-07-09 12:04:38.350 W/System.err:     at a.a.so67958704javaroomconvertexistingdb.AllDao_Impl.update4(AllDao_Impl.java:159)
2021-07-09 12:04:38.350 W/System.err:     at a.a.so67958704javaroomconvertexistingdb.MainActivity.onCreate(MainActivity.java:78)
....
2021-07-09 12:04:38.353 D/BMINFO-D1: ID = 1 PostTitle = P1 PostURL =AnotherURL
2021-07-09 12:04:38.353 D/BMINFO-D1: ID = 2 PostTitle = P2 PostURL =U2
2021-07-09 12:04:38.353 D/BMINFO-D1: ID = 3 PostTitle = P3 PostURL =U3
2021-07-09 12:04:38.353 D/BMINFO-D1: ID = 4 PostTitle = P4 PostURL =U4
2021-07-09 12:04:38.355 D/AndroidRuntime: Shutting down VM
2021-07-09 12:04:38.358 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: a.a.so67958704javaroomconvertexistingdb, PID: 14230
    java.lang.RuntimeException: Unable to start activity ComponentInfo{a.a.so67958704javaroomconvertexistingdb/a.a.so67958704javaroomconvertexistingdb.MainActivity}: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: mylist_data.ID (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)

注意到第一个异常被捕获并打印并且不是致命异常,第二个是。