transaction - Transacciones de la base de datos de Android Room
room database android (3)
Con la nueva base de datos de salas en Android, tengo un requisito donde hay dos operaciones secuenciales que deben realizarse:
removeRows(ids);
insertRows(ids);
Si ejecuto esto, veo (al examinar la base de datos) que faltan algunas filas, supongo que se eliminarán después de insertar. verbigracia. La primera operación se ejecuta en paralelo a la segunda.
Si uso un bloque de transacción, como este, entonces todo está bien, la primera operación parece completarse antes de hacer la segunda:
roomDb.beginTransaction();
removeRows(ids);
roomDb.endTransaction();
insertRows(ids);
También está bien si doy un sueño intermedio en su lugar:
removeRows(ids);
Thread.sleep(500);
insertRows(ids);
No parece haber mucha documentación para la Sala, y me preguntaba si debería usar el bloque de transacciones como el anterior cuando tengo que hacer operaciones secuenciales, o si hay alguna forma mejor de hacerlo.
EDITAR : Después de señalar @CommonsWare, @Query
es asíncrono, mientras que @Insert
y @Delete
son síncronos. En vista de esto, ¿cómo obtendría una consulta que borra filas para que sean asíncronas?
@Query("DELETE from table WHERE id IN(:ids)")
int removeRows(List<Long> ids);
De acuerdo con el resultado de la compilación, obtengo que los Deletion methods must either return void or return int (the number of deleted rows)
, si intento ajustar el tipo de retorno en un Flowable
.
Aquí está la solución a este problema:
@Query("SELECT * FROM friend WHERE id = :id")
Friend getFriendByID(int id);
@Delete
void delete(Friend friend);
Friend friendToBeDeleted = friendDAO.getFriendByID(id);
friendDAO.delete(friendToBeDeleted);
Tienes que pasar por dos pasos!
Como @CommonsWare señaló, @Query es asíncrono, mientras que @Insert, @Delete, @Update son síncronos.
Si desea ejecutar varias consultas en una sola transacción, Room también proporciona un método para eso, como se menciona a continuación.
roomDB.runInTransaction(new Runnable() {
@Override
public void run() {
removeRows(ids);
insertRows(ids);
}
});
Espero que esto resuelva tu problema.
Como se indica en la documentación de Transaction , puede hacer lo siguiente:
@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);
}
}