gpt4 book ai didi

具有延迟外键的 Android Room

转载 作者:行者123 更新时间:2023-11-29 02:20:41 25 4
gpt4 key购买 nike

我有几个定期从服务器更新的表(BenefitBranchCoupon)和另外两个仅在本地的表(FavoriteBenefitUsedCoupon)。 ER图看起来像这样: ER diagram

每当在服务器上删除一个 Benefit 时,我也想从 FavoriteBenefit 中删除一个适当的实体。为此,我可以使用 onDelete = ForeignKey.CASCADE,每当父级 Benefit 不再存在于数据库中时,FavoriteBenefit 也会被删除。听起来不错。

每次使用都会出现问题@Insert(onConflict = OnConflictStrategy.REPLACE) 更新数据库中的 yield 。 REPLACE 实际上执行了 DELETEINSERTDELETE 在内部触发 onDeleteFavoriteBenefit 因此,该表中的所有数据也将被删除。

(类似的问题发生在 CouponUsedCoupon 表中。)


我正在寻找一种在事务结束前暂时禁用外键约束的方法。也就是说,在交易过程中不验证外键,只在交易结束时验证。我仍然希望 Room 自动删除没有有效父实体的实体。


好像标记了foreign key as defferred通过在 @ForeignKey 定义上设置 deferred = true 应该完全符合我想要实现的目标。

boolean deferred ()

A foreign key constraint can be deferred until the transaction is complete. This is useful if you are doing bulk inserts into the database in a single transaction. By default, foreign key constraints are immediate but you can change it by setting this field to true.

但即使我设置了 deferred 标志,它似乎也没有任何效果,因为 FavoriteBenefit 仍然每次都被删除。

我是否错误地理解了 deferred 标志?

最佳答案

我不知道它是否仍然与您相关,但我遇到了类似的问题。我试图将 deferred 标志放在两个地方:关系类本身和作为编译指示。在这两种情况下,项目都因 OnConflictStrategy.REPLACE 策略(如您所述执行 DELETE 操作)而被删除。我发现的解决方法是使用“UPSERT-like”查询。 UPSERT statement 支持是去年在 SQLite 中添加的,所以 Room 还不支持,但是你可以这样写:

@Dao
abstract class BaseDao<T> {

/**
* Insert an item in the database.
*
* @param item the item to be inserted.
* @return The SQLite row id
*/
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract fun insert(item: T): Long

/**
* Insert an array of items in the database.
*
* @param items the items to be inserted.
* @return The SQLite row ids
*/
@Insert(onConflict = OnConflictStrategy.IGNORE)
abstract fun insert(items: List<T>): List<Long>

/**
* Update an item from the database.
*
* @param item the item to be updated
*/
@Update
abstract fun update(item: T)

/**
* Update an array of items from the database.
*
* @param item the item to be updated
*/
@Update
abstract fun update(item: List<T>)

@Transaction
fun upsert(item: T) {
val id = insert(item)
if (id == -1L) {
update(item)
}
}

@Transaction
fun upsert(items: List<T>) {
val insertResult = insert(items)
val updateList = mutableListOf<T>()

for (i in insertResult.indices) {
if (insertResult[i] == -1L) {
updateList.add(items[i])
}
}

if (updateList.isNotEmpty()) {
update(updateList)
}
}
}

代码背后的逻辑很简单 - 如果表已经包含记录(这是在插入后通过过滤 rowid 进行检查) - 我们应该更新它们。

Credits

关于具有延迟外键的 Android Room,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56003734/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com