38

使用 Android 中的新房间数据库,我需要执行两个顺序操作:

removeRows(ids);
insertRows(ids);

如果我运行它,我会看到(在检查数据库时)缺少一些行 - 我假设它们在插入后被删除。即。第一个操作与第二个操作并行运行。

如果我使用这样的事务块,那么一切都很好 - 第一个操作似乎在执行第二个操作之前完成:

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

insertRows(ids);

如果我在中间休息一下也可以:

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

insertRows(ids);

Room 似乎没有太多文档,并且想知道当我要完成顺序操作时是否应该使用上述事务块,或者有没有更好的方法。

编辑:@CommonsWare 指出后,@Query是异步的,而@Insert@Delete是同步的。鉴于此,我将如何获得一个删除异步行的查询:

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

根据我得到的构建输出Deletion methods must either return void or return int (the number of deleted rows),如果我尝试将返回类型包装在Flowable.

4

5 回答 5

44

正如Transaction文档中所指出的,您可以执行以下操作:

 @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);
     }
 }
 
于 2017-10-12T14:24:52.050 回答
30

正如@CommonsWare 指出的那样,@Query 是异步的,而 @Insert、@Delete、@Update 是同步的。

如果您想在单个事务中执行多个查询,Room 还提供了一种方法,如下所述。

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

我希望这能解决你的问题。

于 2017-09-08T04:21:53.307 回答
4

对于 Kotlin 中的 Room 交易,您可以使用:

  • 与已实现方法的接口,例如:
@Dao 
interface Dao {

    @Insert 
    fun insert(item: Item)

    @Delete 
    fun delete(item: Item)

    @Transaction
    fun replace(oldItem: Item, newItem: Item){
        delete(oldItem)
        insert(newItem)
    }

}
  • 或者使用open函数,例如:
@Dao 
abstract class Dao {

    @Insert 
    abstract fun insert(item: Item)

    @Delete 
    abstract fun delete(item: Item)

    @Transaction
    open fun replace(oldItem: Item, newItem: Item){
        delete(oldItem)
        insert(newItem)
    }

}

你会得到error: Method annotated with @Transaction must not be private, final, or abstract.没有open修饰符。

于 2020-01-28T15:08:38.747 回答
1

我相信当我们使用 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)
        }
    }
}
于 2019-08-06T10:12:39.457 回答
-4

这是这个问题的解决方案:

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

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

你必须经过两个步骤!

于 2019-01-26T00:11:33.633 回答