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

Android Room一对多关系报错‘Entities cannot have relations’求助

问题解决与疑问解答

报错原因与修复步骤

核心错误:错误将关系类加入数据库实体列表

你在QuizDatabase的entities数组里添加了QuestionWithAnswers::class,但**QuestionWithAnswers是Room用来表示一对多关系的组合数据类,不是数据库表对应的实体类**,这直接触发了所有报错:

  • error: Entity class must be annotated with @Entity:Room把它当成实体类处理,但它没有@Entity注解
  • error: Entities cannot have relations:实体类不允许包含@Relation注解,而该类中存在这个注解
  • error: An entity must have at least 1 field annotated with @PrimaryKey:实体类必须定义主键,该类没有符合要求的主键字段

修复代码:修改QuizDatabase,移除QuestionWithAnswers::class:

@Database(
    entities = [
            Question::class,
            Answer::class
            ],
    version = 1
)
abstract class QuizDatabase : RoomDatabase () {
    abstract val daoQuestion : Dao_Question
    abstract val daoAnswer : Dao_Answer
    abstract val daoQuestionWithAnswers : Dao_QuestionWithAnswers

    companion object {
        const val DATABASE_NAME = "quiz_db"
    }
}

其他可选优化

  1. 保留你之前尝试的外键约束代码,增强数据一致性:
@Entity(
    tableName = "quiz_answers",
    foreignKeys = [
        ForeignKey(
            entity = Question::class,
            parentColumns = ["ID"],
            childColumns = ["quest_id"],
            onDelete = ForeignKey.CASCADE // 可选:删除题目时自动删除对应答案
        )
    ]
)
data class Answer(
    @PrimaryKey val ID: Int,
    @ColumnInfo(index = true) val quest_id: Int,
    val answer: String,
    val is_true: Boolean
)
  1. 修正QuestionWithAnswers的字段名,符合语义:
data class QuestionWithAnswers(
    @Embedded val question: Question,
    @Relation(
        entity = Answer::class,
        parentColumn = "ID",
        entityColumn = "quest_id"
    )
    val answers: List<Answer> // 一个题目对应多个答案,用复数更合理
)

你的疑问解答

1. 为关系单独创建Dao_、Rep_和Impl_文件是否正确?

是合理的。这种拆分符合MVVM分层思想,将关系查询逻辑与单个实体的CRUD操作分离,代码结构更清晰,后续维护也更方便。

2. 编译器为何认为QuestionWithAnswers数据类应该是实体类?

因为你在QuizDatabase的entities数组中声明了它,Room会默认把数组内的所有类当作数据库实体(对应数据库表)处理,而QuestionWithAnswers只是用来组合查询结果的DTO(数据传输对象),并非实体类。移除后该问题就会消失。

3. 查询结果使用集合作为数据类型是否正确?

对于getQuestionAndAnswers(id: Int)这个根据ID查询单题的接口,返回List<QuestionWithAnswers>虽然能运行,但更严谨的做法是返回QuestionWithAnswers?(允许ID不存在的情况)或QuestionWithAnswers(确保ID一定存在)。如果是查询所有题目带答案,返回List<QuestionWithAnswers>是正确的。

可选修改Dao层代码(更严谨):

@Dao
interface Dao_QuestionWithAnswers {
    @Transaction
    @Query("SELECT * FROM quiz_questions WHERE ID = :id")
    fun getQuestionAndAnswers(id: Int): QuestionWithAnswers?
}

对应的仓库、UseCase需要同步修改返回类型。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 11:25:07