在房间ORM中批量插入或更新

and*_*der 3 android android-room

我正在尝试与Android Room ORM一起使用。许多ORM都有此方法insertOrUpdate方法。我该如何实现?我想在单个事务中插入或更新多行,即如果存在行,则更新它,否则插入一个新条目。

Xav*_*ana 6

您可以执行将冲突解决方案设置为replace的插入:

@Dao
public interface MyDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public void insertUsers(User... users);
}
Run Code Online (Sandbox Code Playgroud)

请注意(来自“ 房间”文档):

注意:SQLite将@Insert(onConflict = REPLACE)处理为一组REMOVE和REPLACE操作,而不是单个UPDATE操作。这种替换冲突值的方法可能会影响您的外键约束。有关更多详细信息,请参见SQLite文档中的ON_CONFLICT子句。

在Room中,此单个insert语句在事务内运行,因此大多数时候应该是安全的。

或者,您可以在事务内运行语句:

myDb.runInTransaction(new Runnable() {
     @Override
     public void run() {
         // Your operations
     }
});
Run Code Online (Sandbox Code Playgroud)

或者,从另一个StackOverflow 答案:

@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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Sof*_*uni 6

对于批量事务插入/更新,您可以执行事务注释:

使用 @Transaction 注释方法可确保您在该方法中执行的所有数据库操作都将在一个事务中运行。当方法体中抛出异常时,事务将失败。

@Dao
abstract class UserDao {

    @Transaction
    open fun updateData(users: List<User>) {
        deleteAllUsers()
        insertAll(users)
    }
    @Insert
    abstract fun insertAll(users: List<User>)
    @Query("DELETE FROM Users")
    abstract fun deleteAllUsers()
}
Run Code Online (Sandbox Code Playgroud)

在以下情况下,您可能希望对具有 select 语句的 @Query 方法使用 @Transaction 批注:

当查询的结果相当大时。通过在一个事务中查询数据库,您可以确保如果查询结果不适合单个光标窗口,它不会因光标窗口交换之间的数据库更改而损坏。当查询结果是带有@Relation 字段的 POJO 时。这些字段是单独的查询,因此在单个事务中运行它们将保证查询之间的结果一致。具有多个参数的@Delete、@Update 和@Insert 方法会在事务内自动运行。


and*_*der 0

首先进行更新,然后使用 onConflict 策略插入为 IGNORE