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" } }
其他可选优化
- 保留你之前尝试的外键约束代码,增强数据一致性:
@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 )
- 修正
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
相关产品推荐
相关产品推荐

