批量写入 → Room 事务
老写法(Java + SQLite)
java
// 逐条插入 --- 慢
for (Item item : items) {
ContentValues values = new ContentValues();
values.put("name", item.getName());
values.put("price", item.getPrice());
db.insert("item", null, values);
}
// 手动事务
db.beginTransaction();
try {
for (Item item : items) {
ContentValues values = new ContentValues();
values.put("name", item.getName());
values.put("price", item.getPrice());
db.insert("item", null, values);
}
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
问题在哪里
不用事务时,每条 insert 都是一次独立的磁盘写入,1000 条数据可能要几秒甚至十几秒。手动开事务样板代码又多又容易漏掉 setTransactionSuccessful / endTransaction。忘写一个数据就不持久。
新写法(Room + Kotlin)
kotlin
// 批量插入 --- 单条 @Insert 支持可变参数和 List
@Insert
suspend fun insertAll(items: List<Item>)
// 或直接在 DAO 里定义事务
@Transaction
suspend fun replaceAll(items: List<Item>) {
deleteAll()
insertAll(items)
}
// Repository 层用 withTransaction
class ItemRepository(private val db: AppDatabase, private val dao: ItemDao) {
suspend fun importItems(items: List<Item>) {
db.withTransaction {
for (item in items) {
dao.insert(item)
}
}
}
}
一句话注意
Room 的 @Insert 传 List 时内部已经用事务包装,不必手动再套一层事务。但如果需要在一个事务里执行不同类型的操作(先删后插、多表更新),用 @Transaction 注解或 withTransaction。
@Transaction 用在 DAO 的 suspend 方法上时,Room 保证方法体在一个数据库事务里执行。但不能用在返回 Flow 的方法上------Flow 是长时间运行的观察者,事务只在单次数据库操作期间存在。
Java Android 老项目迁移系列,持续更新中。