如何使用Room Db返回Rx Single事务?

4
假设有一个名为Dao的类,其中包含以下两个方法:

1)

delete(items: List<Item>): Completable

2)

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

我该如何将它们链接在一个以 '删除方法' 开始且返回 '插入方法' 结果的 Dao 类的 @transaction 方法中?

我希望有一个这样的签名:

@Transaction
fun deleteAndInsert(): Single<List<Long> > {
    ...
}
5个回答

5

我假设你的主要目标是让deleteAndInsert()函数的返回类型为Single

你可以通过进行小的修改来实现这一点。

  • 首先使delete()insert()函数同步。
  • 由于@Transaction只能同步工作,我们需要创建另一个函数来调用delete()insert()。此外,请使用@Transaction注解此函数。
  • 创建另一个新函数,它创建一个Single并调用上述函数。

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

我认为这是不可能的。

我曾经尝试过,但我收到了一个编译时错误,说:

"使用@Transaction注释的方法不能返回延迟/异步返回类型io.reactivex.Single。由于事务是线程限制的,Room无法保证方法实现中的所有查询都在同一线程上执行,因此只允许同步的@Transaction实现方法。如果启动事务并进行线程更改并等待,那么如果另一个线程尝试执行查询,则可能发生数据库死锁。这个限制可以防止这种情况发生。"


0
  • 使用@Transaction注解的方法不能返回延迟/异步返回类型io.reactivex.Single。由于事务是线程限定的,Room无法保证方法实现中的所有查询都在同一线程上执行,因此只允许同步的@Transaction方法实现。如果启动了一个事务,并且进行了线程切换并等待,那么如果额外的线程尝试执行查询,则可能发生数据库死锁。这个限制可以防止这种情况发生。
  • 当我将代码反编译为Java时,我看到。

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

0
获取新数据的ID
然后删除所有不在新数据中的项目。
@Query("DELETE FROM product WHERE id NOT IN(:idsNewItems)")
    @Override
    public abstract void deleteOldItems(List<String> idsNewItems)

;


-1

如果您的deleteinsert方法被标记了注释,它们将在事务中执行。因此,基本上您不需要使用此注释标记您的deleteAndInsert方法。那么:

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

3
我不认为它们会在同一笔交易中被执行。 - EpicPandaForce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接