在 Room ORM 中批量插入或更新

Batch InsertOrUpate in Room ORM

我正在尝试 android 房间 ORM。许多 ORM 都有这种方法 insertOrUpdate 方法。我如何实现这一目标?我想在单个事务中插入或更新多行,即,如果存在行则更新它,否则插入一个新条目。

您可以使用 conflict resolution set to replace:

进行插入
@Dao
public interface MyDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public void insertUsers(User... users);
}

注意(来自Room documentation):

Note: SQLite handles @Insert(onConflict = REPLACE) as a set of REMOVE and REPLACE operations instead of a single UPDATE operation. This method of replacing conflicting values could affect your foreign key constraints. For more details, see the SQLite documentation for the ON_CONFLICT clause.

在 Room 中,这个单一的插入语句 运行 在一个事务中,所以它在大多数时候应该是安全的。

或者,您可以 运行 交易中的声明:

myDb.runInTransaction(new Runnable() {
     @Override
     public void run() {
         // Your operations
     }
});

或者,从另一个 Whosebug answer:

@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);
    }
}

先做了update然后insert with onConflict strategy for insertion as IGNORE

对于批量交易insert/update你可以做交易注释:

使用@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()
}

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

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

你也可以这样做

@Insert
suspend fun insertAll(vararg users: User)