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

使用Room构建时触发StackOverflowError问题求助

解决Room框架中自引用实体使用@Relation导致的StackOverflowError

我之前也碰到过这个问题,这是Room处理自引用关联时的典型坑——你的Category实体类同时承担了数据库表模型(带@Entity注解)和关联查询结果模型(带@Relation的subcategories字段)的角色,形成了循环依赖,导致KAPT在编译分析时无限递归,最终触发栈溢出。

问题根源

你的Category类里,subcategories是List<Category>,而Category本身又包含subcategories,这种自引用结构让Room的注解处理器在生成代码时陷入无限递归,超过了JVM的栈深度限制,抛出StackOverflowError。

解决方案:拆分实体与关联模型

正确的做法是把数据库表实体和带关联的查询结果模型分开,避免同一个类同时承担两种角色:

1. 创建纯数据库实体类

这个类只负责定义数据库表的结构,不包含任何@Relation字段:

@Entity(
    foreignKeys = [
        ForeignKey(
            entity = CategoryEntity::class,
            parentColumns = ["id"],
            childColumns = ["parentId"]
        )
    ]
)
data class CategoryEntity(
    val type: Byte,
    val name: String,
    val description: String,
    var parentId: Long? = null,
    var remoteId: Long? = null,
    @PrimaryKey(autoGenerate = true) val id: Long = 0L
)

2. 创建带关联的查询结果模型

单独定义一个类,用来封装实体和它的子分类关联,这个类不需要@Entity注解:

data class CategoryWithSubcategories(
    @Embedded val category: CategoryEntity,
    @Relation(
        parentColumn = "id",
        entityColumn = "parentId"
    )
    val subcategories: List<CategoryWithSubcategories>? = null
)

3. 修改Dao层查询方法

在Dao中使用新的查询模型,并且必须加上@Transaction注解(因为@Relation需要在事务中执行关联查询):

@Dao
interface CategoryDao {
    @Transaction
    @Query("SELECT * FROM CategoryEntity WHERE parentId IS NULL")
    suspend fun getRootCategoriesWithSubcategories(): List<CategoryWithSubcategories>
}

为什么这样能解决问题?

拆分后,Room的注解处理器处理@Relation时,递归的是CategoryWithSubcategories而非数据库实体本身,打破了原有的循环依赖链。同时,这种设计也更符合Room的架构理念:实体类只映射数据库表,关联模型专门处理查询结果的层级结构。

如果需要更新或插入数据,直接操作CategoryEntity即可;CategoryWithSubcategories仅用于查询和展示层级化的分类数据。

内容的提问来源于stack exchange,提问作者Dr.Zoidberg

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:24:59