web-dev-qa-db-ja.com

Androidルームデータベーストランザクション

Androidの新しいルームデータベースでは、2つの連続した操作を行う必要があるという要件があります。

_removeRows(ids);
insertRows(ids);
_

これを実行すると、いくつかの行が欠落していることが(dbを調べると)表示されます-挿入後に削除されていると思います。つまり最初の操作は2番目の操作と並行して実行されます。

このようなトランザクションブロックを使用する場合は、問題ありません。最初の操作は2番目の操作を行う前に完了したようです。

_roomDb.beginTransaction();
removeRows(ids);
roomDb.endTransaction();

insertRows(ids);
_

代わりに中間に睡眠を与えても大丈夫です:

_removeRows(ids);
Thread.sleep(500);

insertRows(ids);
_

ルームのドキュメントはあまりないようで、シーケンシャル操作を実行するときに上記のようなトランザクションブロックを使用する必要があるのか​​、それとももっと良い方法があるのか​​疑問に思っていました。

[〜#〜] edit [〜#〜]:@CommonsWareが指摘した後、_@Query_は非同期ですが、_@Insert_と_@Delete_は同期です。これを考慮して、非同期にする行を削除するクエリをどのように取得しますか:

_@Query("DELETE from table WHERE id IN(:ids)")
int removeRows(List<Long> ids);
_

ビルド出力によると、Flowableで戻り値の型をラップしようとすると、Deletion methods must either return void or return int (the number of deleted rows)が返されます。

20
rajath

トランザクション のドキュメントで指摘されているように、次のことができます。

 @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);
     }
 }
25
guness

@CommonsWareが指摘したように、@ Queryは非同期ですが、@Insert、@Delete、@Updateは同期です。

単一のトランザクションで複数のクエリを実行する場合、Roomは以下で説明する方法も提供します。

roomDB.runInTransaction(new Runnable() {
        @Override
        public void run() {
            removeRows(ids);
            insertRows(ids);
        }
    });

これで問題が解決することを願っています。

15
Pinakin

この問題の解決策は次のとおりです。

@Query("SELECT * FROM friend WHERE id = :id")
Friend getFriendByID(int id);
@Delete
void delete(Friend friend);

Friend friendToBeDeleted = friendDAO.getFriendByID(id);
friendDAO.delete(friendToBeDeleted);

あなたは2つのステップを経なければなりません!

0
David

DAOインターフェイスを使用している場合でも、デフォルトのインターフェイスメソッドを使用してトランザクションを実行できると考えています。アノテーション@JvmDefaultおよび@Transactionを追加する必要があり、その内部で単一のトランザクションに属する任意の操作を実行できます。

@Dao
interface TestDao {
    @Insert
    fun insert(dataObj: DataType)

    @Update
    fun update(dataObj: DataType): Completable

    @Delete
    fun delete(dataObj: DataType): Completable

    @Query("DELETE FROM $TABLE_NAME")
    fun deleteAllData()

    @Query("SELECT * FROM $TABLE_NAME ORDER BY id DESC")
    fun getAllData(): Single<List<DataType>>

    @JvmDefault
    @Transaction
    fun singleTransaction(dataList: List<DataType>) {
        deleteAllData()
        dataList.forEach {
            insert(it)
        }
    }
}
0
AK Ali