You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Room外键约束失败(787):如何实现文件夹系统?

解决Room数据库删除Folder时的外键约束失败问题

看起来你遇到的是典型的外键关联引用未清理导致的约束错误——当你删除Folder表的记录时,WebSitesWithFolders关联表中还存在引用该folder_id的条目,而Room默认的外键行为是RESTRICT(禁止删除有子记录引用的父条目),所以抛出了代码787的错误。下面是具体的解决方案:

核心思路:设置外键级联删除

要让Room在删除Folder时自动清理关联表中的对应记录,你需要在WebSitesWithFolders实体的外键定义中添加onDelete = ForeignKey.CASCADE规则。

步骤1:修正关联表的外键配置

首先检查你的WebSitesWithFolders实体,确保它的外键定义包含级联删除逻辑:

@Entity(
    tableName = "WebSitesWithFolders",
    primaryKeys = ["webSites_id", "folders_id"],
    foreignKeys = [
        // 网站与关联表的外键(可选添加级联,根据你的业务需求)
        ForeignKey(
            entity = WebSites::class,
            parentColumns = ["id"], // 对应WebSites的主键字段
            childColumns = ["webSites_id"],
            onDelete = ForeignKey.CASCADE
        ),
        // 关键:文件夹与关联表的外键,添加级联删除
        ForeignKey(
            entity = Folders::class,
            parentColumns = ["id"], // 对应Folders的主键字段
            childColumns = ["folders_id"],
            onDelete = ForeignKey.CASCADE // 删除文件夹时,自动删除关联表中相关记录
        )
    ]
)
data class WebSitesWithFolders(
    val webSites_id: Long,
    val folders_id: Long
)

步骤2:更新数据库版本

修改外键定义属于数据库 schema 变更,你需要更新Room数据库的版本号:

@Database(
    entities = [WebSites::class, Folders::class, WebSitesWithFolders::class],
    version = 2, // 版本号比之前的数值+1
    exportSchema = true
)
abstract class AppDatabase : RoomDatabase() {
    // 声明你的DAO接口
    abstract fun webSiteDao(): WebSiteDao
    abstract fun folderDao(): FolderDao
    abstract fun webSitesWithFoldersDao(): WebSitesWithFoldersDao
}

如果是开发阶段不想写迁移代码,可以临时启用破坏性迁移(会清空数据库数据,上线前记得去掉):

Room.databaseBuilder(context, AppDatabase::class.java, "your_db_name")
    .fallbackToDestructiveMigration()
    .build()

备选方案:手动事务删除(不推荐)

如果你暂时不想修改外键配置,也可以通过DAO的事务先删除关联表记录,再删除文件夹:

@Dao
interface FolderDao {
    @Transaction
    suspend fun deleteFolderAndAssociations(folderId: Long) {
        // 第一步:删除关联表中该文件夹的所有关联记录
        deleteWebSitesWithFoldersByFolderId(folderId)
        // 第二步:删除文件夹本身
        deleteFolderById(folderId)
    }

    @Query("DELETE FROM WebSitesWithFolders WHERE folders_id = :folderId")
    suspend fun deleteWebSitesWithFoldersByFolderId(folderId: Long)

    @Query("DELETE FROM Folders WHERE id = :folderId")
    suspend fun deleteFolderById(folderId: Long)
}

验证效果

完成上述配置后,当你调用Folder的删除方法时,Room会自动清理WebSitesWithFolders中对应的关联记录,不会再触发外键约束失败的错误。

内容的提问来源于stack exchange,提问作者Сергей

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:21:14