How to return a Rx Single transaction using Room Db?

故事扮演 提交于 2020-06-16 02:00:02

问题


Suppose there is a Dao class with the following two methods:

1)

delete(items: List<Item>): Completable

2)

 insert(items: List< Item >): Single<List<Long>>

How can I chain them into a @transaction method in Dao class starting with ‘delete method’ and then returning ‘insert method’ result?

I want to have a method with a signature like this:

@Transaction
fun deleteAndInsert(): Single<List<Long> > {
    ...
}

回答1:


I'm assuming your main goal is to have the return type of deleteAndInsert() as Single.

You can achieve that with small modifications

  • first by making delete() and insert() functions synchronous.
  • Since @Transaction only works synchronously, we need to create another function that calls both delete() and insert(). Also, annotate this function with @Transaction
  • Create another new function that creates a Single and calls the above function.

abstract class SampleDao{
    protected abstract fun delete()
    protected abstract fun insert(items: List<Item>) : List<Long>

    @Transaction
    protected open fun deleteAndInsertSync(items: List<Item>): List<Long>{
        delete()
        return insert(items)
    }

    fun deleteAndInsert(items:List<Item>): Single<List<Long>>{
        return Single.create {
            it.onSuccess(deleteAndInsertSync(items))
        }
    }
}



回答2:


I don't think it is possible.

I once tried it and I got a compile-time error saying:

"Method annotated with @Transaction must not return deferred/async return type io.reactivex.Single. Since transactions are thread confined and Room cannot guarantee that all queries in the method implementation are performed on the same thread, only synchronous @Transaction implemented methods are allowed. If a transaction is started and a change of thread is done and waited upon then a database deadlock can occur if the additional thread attempts to perform a query. This restriction prevents such situation from occurring."




回答3:


If you delete and insert methods are marked with annotation, they are executing in a transaction. So, basicly you don't need to mark your deleteAndInsert method with this annotation. So, than:

fun deleteAndInsert(items: List< Item >): Single<List<Long>> {
    return delete().andThan(insert(items))
}



回答4:


  • Method annotated with @Transaction must not return deferred/async return type io.reactivex.Single. Since transactions are thread confined and Room cannot guarantee that all queries in the method implementation are performed on the same thread, only synchronous @Transaction implemented methods are allowed. If a transaction is started and a change of thread is done and waited upon then a database deadlock can occur if the additional thread attempts to perform a query. This restrictions prevents such situation from occurring.
  • When I decompile code to java, I see.

    public interface CustomerDao {
    @Transaction
    @NotNull
    List deleteAndCreate(@NotNull List var1);
    
    @Query("DELETE FROM customer")
    @NotNull
    Completable deleteAll();
    
    @Insert
    @NotNull
    List insertAll(@NotNull List var1);
    
    @Metadata(
       mv = {1, 1, 15},
       bv = {1, 0, 3},
       k = 3
    )
    public static final class DefaultImpls {
       @Transaction
       @NotNull
       public static List deleteAndCreate(CustomerDao $this, @NotNull List 
         users) 
       {
          Intrinsics.checkParameterIsNotNull(users, "users");
          $this.deleteAll();
          return $this.insertAll(users);
       }
    }
    }
    



回答5:


Get Ids of new Data

then delete all items where not in the new data

@Query("DELETE FROM product WHERE id NOT IN(:idsNewItems)")
    @Override
    public abstract void deleteOldItems(List<String> idsNewItems)

;



来源:https://stackoverflow.com/questions/55463342/how-to-return-a-rx-single-transaction-using-room-db

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!