@Transaction注解与Flowable不兼容。

huangapple go评论79阅读模式
英文:

Room @Transaction not working with Flowable

问题

我在使用@Transaction注解在我的数据源方法上遇到了问题。在我的情况下,这个注解似乎不起作用。

我有一个常规的Room数据库和DAO:

@Database(entities = [MyEntity::class], version = 1)
abstract class MyDatabase : RoomDatabase() {
    abstract fun myDao(): MyDao
}

@Dao
interface MyDao {
    @Insert
    fun insertAll(list: List<MyEntity>)

    @Query("SELECT * FROM MyEntity")
    fun observe(): Flowable<List<MyEntity>>

    @Query("DELETE FROM MyEntity")
    fun clear()
}

问题出现在我连续使用clear()insertAll()时的数据源中:

class MyDataSource(database: MyDatabase) {
    private val myDao = database.myDao()

    @Transaction
    fun updateMyEntity(items: List<MyEntity>) {
        myDao.clear()
        myDao.insertAll(items)
    }

    fun observeMyEntity(): Flowable<List<MyEntity>> {
        return myDao.observe()
    }
}

当我调用updateMyEntity()时,在我的oberveMyEntity()订阅中会得到两个结果。第一个结果是空列表,第二个结果是插入的列表。我期望只得到插入的列表,因为我在updateMyEntity()方法上添加了@Transaction注解。这个注解在我的情况下不起作用吗?

我在文档中看到了以下信息,但我不确定是否适用于我的情况:

如果查询是异步的(例如返回{@link androidx.lifecycle.LiveData LiveData}或RxJava {@code Flowable}),事务会在查询运行时得到正确处理,而不是在方法调用时。

将此注解放在{@link Insert}、{@link Update}或{@link Delete}方法上没有任何影响,因为这些方法总是在事务内部运行。类似地,如果一个方法被{@link Query}注解标记,但运行的是INSERT、UPDATE或DELETE语句,它会自动被包装在一个事务中,这个注解不起作用。

如果将database设置为属性,并使用database.runInTransaction { }包装调用clear()insertAll(),问题就会消失。

英文:

I have a problem with using @Transaction annotation on my data source method. Looks like this annotation not working in my case.

I have a usual room database with DAO

@Database(entities = [MyEntity::class], version = 1)
abstract class MyDatabase : RoomDatabase() {
    abstract fun myDao(): MyDao
}

@Dao
interface myDao {
    @Insert
    fun insertAll(list: List&lt;MyEntity&gt;)
    
    @Query(&quot;SELECT * FROM MyEntity&quot;)
    fun observe(): Flowable&lt;List&lt;MyEntity&gt;&gt;

    @Query(&quot;DELETE FROM MyEntity&quot;)
    fun clear()
}

Problem appears in my data source when I do consistently clear() and insertAll()

class MyDataSource(database: MyDatabase) {
    private val myDao = database.myDao()

    @Transaction
    fun updateMyEntity(items: List&lt;MyEntity&gt;) {
        myDao.clear()
        myDao.insertAll(items)
    }

    fun observeMyEntity(): Flowable&lt;List&lt;MyEntity&gt;&gt; {
        return myDao.observe()
    }
}

When I call updateMyEntity(), I get two results in my subscription on oberveMyEntity(). The first result is empty list and the second one is inserted list. I expected to get only inserted list as I added annotation @Transaction to method updateMyEntity(). Is this annotation not working in my case?

I saw in docs the following information, but I am not sure is it my case or not.

> If the query is asynchronous (e.g. returns a {@link androidx.lifecycle.LiveData LiveData}
or RxJava {@code Flowable}), the transaction is properly handled when the query is run, not when
the method is called.
>
> Putting this annotation on an {@link Insert}, {@link Update} or {@link Delete} method has no
impact because those methods are always run inside a transaction. Similarly, if a method is
annotated with {@link Query} but runs an INSERT, UPDATE or DELETE statement, it is automatically wrapped in a transaction and this annotation has no effect.

The problem disappears if make database a property and wrap calls clear() and insertAll() with database.runInTransaction { }.

答案1

得分: 1

Transaction 只能用于 Dao 方法。

英文:

Transaction can only be used for Dao methods

huangapple
  • 本文由 发表于 2020年8月19日 21:57:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/63488626.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定