You need to enable JavaScript to run this app. Android Room多层嵌套关联实现及no such column报错修复
优惠活动
大模型
产品
解决方案
定价
更多

Android Room多层嵌套关联实现及no such column报错修复

问题原因

报错的核心是@Relation关联配置存在链路断层:

  • 你需要实现的层级关系为:Training → 关联多个Exercise → 每个Exercise关联多个Set → 每个Set关联对应SetType
  • 原代码在TrainingWithExerciseWithSets中配置@Relation时直接指定entity = Set::class,意味着Room会从set_table表读取全量字段来映射返回值。但返回值类型是List<ExerciseWithSets>,该类型依赖的exerciseName等字段存储在exercise_table中,set_table没有对应列,查询时就会触发no such column的报错。
  • 原配置的本质问题是跳过了Exercise层级,直接让Room从Set表读数据硬映射为Exercise类型的对象,根本无法拿到Exercise表存储的字段。
修复方法

由于Set表同时持有trainingId和exerciseId两个外键,是连接Training和Exercise的天然中间表,可以通过Room提供的Junction桥接能力打通正确的关联链路,无需改动原有ExerciseWithSets、SetAndSetType的正确配置:

  • 调整TrainingWithExerciseWithSets的@Relation参数,将关联目标改为Exercise实体,通过Junction指定桥接的Set表,正确映射两边的关联列

修改后的代码如下:

@Parcelize
data class TrainingWithExerciseWithSets(
    @Embedded
    val training: Training,
    @Relation(
        parentColumn = "trainingId", // Training实体的主键
        entityColumn = "exerciseId", // Exercise实体的主键
        associateBy = Junction(
            value = Set::class, // 作为桥接的中间表实体
            parentColumn = "trainingId", // 桥接表中关联Training的列
            entityColumn = "exerciseId" // 桥接表中关联Exercise的列
        )
    )
    val exercises: List<ExerciseWithSets>
) : Parcelable
配套排查点
  • 修改完成后Room生成的查询逻辑会按层级递归执行:先查询当前Training的基础信息 → 遍历Set表匹配和当前Training关联的所有不重复ExerciseId → 查询Exercise表拿到包括exerciseName在内的完整Exercise数据 → 对每个Exercise递归解析嵌套关联,拿到对应的Set列表、每个Set关联的SetType信息,不会再出现列不存在的问题
  • 建议将Room数据库版本号自增1,避免旧版本数据库结构、错误生成的查询逻辑残留引发二次报错

内容的提问来源于stack exchange,提问作者Octane

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.13 15:15:09