Skip to content Skip to sidebar Skip to footer

How To Return A Rx Single Transaction Using Room Db?

Suppose there is a Dao class with the following two methods: 1) delete(items: List): Completable 2) insert(items: List< Item >): Single>

Solution 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))
        }
    }
}

Solution 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."


Solution 3:

  • 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);
       }
    }
    }
    

Solution 4:

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)

;


Solution 5:

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))
}

Post a Comment for "How To Return A Rx Single Transaction Using Room Db?"