[英]Android Room database transactions
使用 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);
根据构建输出,如果我尝试将返回类型包装在Flowable
,则Deletion methods must either return void or return int (the number of deleted rows)
。
正如Transaction文档中所指出的,您可以执行以下操作:
@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);
}
}
正如@CommonsWare 指出的那样,@Query 是异步的,而@Insert、@Delete、@Update 是同步的。
如果您想在单个事务中执行多个查询,Room 还提供了一种方法,如下所述。
roomDB.runInTransaction(new Runnable() {
@Override
public void run() {
removeRows(ids);
insertRows(ids);
}
});
我希望这能解决你的问题。
对于 Kotlin 中的房间事务,您可以使用:
@Dao
interface Dao {
@Insert
fun insert(item: Item)
@Delete
fun delete(item: Item)
@Transaction
fun replace(oldItem: Item, newItem: Item){
delete(oldItem)
insert(newItem)
}
}
@Dao
abstract class Dao {
@Insert
abstract fun insert(item: Item)
@Delete
abstract fun delete(item: Item)
@Transaction
open fun replace(oldItem: Item, newItem: Item){
delete(oldItem)
insert(newItem)
}
}
你会得到error: Method annotated with @Transaction must not be private, final, or abstract.
没有打开修饰符。
我相信当我们使用 DAO 接口时,我们仍然可以使用默认的接口方法执行事务。 我们需要添加注解@JvmDefault 和@Transaction,我们可以在其中执行任何属于单个事务的操作。
@Dao
interface TestDao {
@Insert
fun insert(dataObj: DataType)
@Update
fun update(dataObj: DataType): Completable
@Delete
fun delete(dataObj: DataType): Completable
@Query("DELETE FROM $TABLE_NAME")
fun deleteAllData()
@Query("SELECT * FROM $TABLE_NAME ORDER BY id DESC")
fun getAllData(): Single<List<DataType>>
@JvmDefault
@Transaction
fun singleTransaction(dataList: List<DataType>) {
deleteAllData()
dataList.forEach {
insert(it)
}
}
}
这是这个问题的解决方案:
@Query("SELECT * FROM friend WHERE id = :id")
Friend getFriendByID(int id);
@Delete
void delete(Friend friend);
Friend friendToBeDeleted = friendDAO.getFriendByID(id);
friendDAO.delete(friendToBeDeleted);
你必须经过两个步骤!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.