Как вернуть одиночную транзакцию Rx с использованием Room Db?

#android #rx-java2 #android-room

#Android #rx-java2 #android-room

Вопрос:

Предположим, что существует Dao класс со следующими двумя методами:

1)

 delete(items: List<Item>): Completable
  

2)

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

Как я могу объединить их в @transaction метод в Dao классе, начиная с «метода удаления», а затем возвращая результат ‘метода вставки’?

Я хочу иметь метод с подписью, подобной этой:

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

Ответ №1:

Я предполагаю, что ваша главная цель — иметь возвращаемый тип deleteAndInsert() as 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.Одиночный. Поскольку транзакции ограничены потоком, и Room не может гарантировать, что все запросы в реализации метода выполняются в одном потоке, разрешены только методы, реализованные синхронно @Transaction. Если транзакция запущена и выполняется смена потока и ожидается, то может возникнуть взаимоблокировка базы данных, если дополнительный поток попытается выполнить запрос. Это ограничение предотвращает возникновение такой ситуации.»

Ответ №3:

  • Метод, помеченный @Transaction, не должен возвращать отложенный / асинхронный тип возврата io.reactivex.Одиночный. Поскольку транзакции ограничены потоком, и 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);
       }
    }
    }
      

Ответ №4:

Получить идентификаторы новых данных

затем удалите все элементы, которых нет в новых данных

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

;

Ответ №5:

Если вы delete и insert методы отмечены аннотацией, они выполняются в транзакции. Итак, в принципе, вам не нужно помечать свой deleteAndInsert метод этой аннотацией. Итак, чем:

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

Комментарии:

1. Я не думаю, что тогда они будут выполнены в одной транзакции.