Вопрос:

Транзакции базы данных Android Room

android transactions android-database android-room

16059 просмотра

4 ответа

9153 Репутация автора

С новой базой данных комнат в Android у меня есть требование, при котором необходимо выполнить две последовательные операции:

removeRows(ids);
insertRows(ids);

Если я запускаю это, я вижу (при проверке БД), что отсутствуют некоторые строки - я предполагаю, что они удаляются после вставки. а именно первая операция выполняется параллельно второй.

Если я использую блок транзакции, такой как этот, то все нормально - первая операция, кажется, завершается перед выполнением второй:

roomDb.beginTransaction();
removeRows(ids);
roomDb.endTransaction();

insertRows(ids);

Также хорошо, если я посплю вместо этого:

removeRows(ids);
Thread.sleep(500);

insertRows(ids);

Кажется, что для Room не так много документации, и мне было интересно, должен ли я использовать блок транзакций, как описано выше, когда у меня есть последовательные операции, или есть ли лучший способ сделать это.

РЕДАКТИРОВАТЬ : После того, как @CommonsWare указал, @Queryявляются асинхронными, а @Insertи @Deleteсинхронными. В связи с этим, как бы я получить запрос, который удаляет строки, чтобы быть асинхронными:

@Query("DELETE from table WHERE id IN(:ids)")
int removeRows(List<Long> ids);

Согласно полученному результату сборки Deletion methods must either return void or return int (the number of deleted rows), если я пытаюсь обернуть возвращаемый тип в Flowable.

Автор: rajath Источник Размещён: 23.06.2017 02:00

Ответы (4)


14 плюса

956 Репутация автора

Как указал @CommonsWare, @Query асинхронный, а @Insert, @Delete, @Update синхронные.

Если вы хотите выполнить несколько запросов в одной транзакции, Room также предоставляет метод для этого, как указано ниже.

roomDB.runInTransaction(new Runnable() {
        @Override
        public void run() {
            removeRows(ids);
            insertRows(ids);
        }
    });

Я надеюсь, что это решит вашу проблему.

Автор: Pinakin Размещён: 08.09.2017 04:21

25 плюса

3287 Репутация автора

как указано в документации по Транзакции , вы можете сделать следующее:

 @Dao
 public abstract class ProductDao {
    @Insert
    public abstract void insert(Product product);

    @Delete
    public abstract void delete(Product product);

    @Transaction
    public void insertAndDeleteInTransaction(Product newProduct, Product oldProduct) {
         // Anything inside this method runs in a single transaction.
         insert(newProduct);
         delete(oldProduct);
     }
 }
Автор: guness Размещён: 12.10.2017 02:24

0 плюса

1 Репутация автора

Вот решение этой проблемы:

@Query("SELECT * FROM friend WHERE id = :id")
Friend getFriendByID(int id);
@Delete
void delete(Friend friend);

Friend friendToBeDeleted = friendDAO.getFriendByID(id);
friendDAO.delete(friendToBeDeleted);

Вы должны пройти два шага!

Автор: David Размещён: 26.01.2019 12:11

0 плюса

104 Репутация автора

Я считаю, что когда мы используем интерфейсы DAO, мы все равно можем выполнять транзакции, используя методы интерфейса по умолчанию. Нам нужно добавить аннотации @JvmDefault и @Transaction, и мы можем выполнять внутри нее любые операции, которые принадлежат одной транзакции.

@Dao
interface TestDao {
    @Insert
    abstract fun insert(dataObj: DataType)

    @Update
    abstract fun update(dataObj: DataType): Completable

    @Delete
    abstract fun delete(dataObj: DataType): Completable

    @Query("DELETE FROM $TABLE_NAME")
    abstract fun deleteAllData()

    @Query("SELECT * FROM $TABLE_NAME ORDER BY id DESC")
    abstract fun getAllData(): Single<List<DataType>>

    @JvmDefault
    @Transaction
    open fun singleTransaction(dataList: List<DataType>) {
        deleteAllData()
        dataList.forEach {
            insert(it)
        }
    }
}
Автор: AK Ali Размещён: 06.08.2019 10:12
Вопросы из категории :
32x32