sqlite 未结束违反延迟外键约束的事务

e5nqia27  于 2022-11-15  发布在  SQLite
关注(0)|答案(1)|浏览(130)

我有一个Room数据库,实体为ABB通过外键引用A。将外键设置为延迟到事务结束:

@ForeignKey(entity = A.class, deferred = true, parentColumns = "_id", childColumns = "A_id")

当我在事务中删除A中被B中的行引用的行时(例如,使用RoomDatabase.runInTransaction()),事务失败,并且如预期的那样抛出SQLiteConstraintException。但是,当我尝试在同一数据库对象上启动另一个事务时,我得到以下异常:
异常:无法在事务内启动事务(代码1 SQLITE_ERROR)
此外,还会将以下内容打印到LogCAT:
E/SQLiteLog:(1)语句在3:[Begin Exclusive;]中止时无法在事务内启动事务
因此,在抛出SQLiteConstraintException时,初始事务看起来并没有在底层SQLite层中结束。这是故意的行为吗?
从这种状态来看,似乎没有一种方法来结束基础交易。调用RoomDatabase.inTransaction()将生成false,而RoomDatabase.endTransaction()(标记为过时)不会结束事务。
我使用的是房间版本2.1.0。

nbnkbykc

nbnkbykc1#

发生这种情况是因为SQLiteDatabase类中的bug:如果您将FK设置为可推迟的初始延迟,并且在事务期间失败,则在Commit()之后,数据库会话控制器将处于不稳定状态,既不允许新事务,也不关闭前一个事务。
有一个workaround:关闭数据库并再次打开它。这将正确更新交易状态。
我更喜欢在提交事务之前手动检查FK约束,并在违反FK的情况下抛出SQLiteConstraintException异常。可以使用PRAGMA foreign_key_check进行检查

相关问题