Room框架一对多关联:如何构建包含两个关联列表的组合数据类
在Room中实现单个实体关联两个列表的解决方案
没问题,这个需求Room完全支持,你只需要在现有的组合数据类里新增一个带@Relation注解的列表字段就可以搞定,我给你一步步说明:
1. 先定义Steps实体类
首先你需要创建Step实体,和KeyIngredients类似,通过recipeName字段和Recipe建立外键关联:
@Entity data class Step( @PrimaryKey(autoGenerate = true) val stepId: Int, // 可以根据需求用自增ID,或者复合主键(比如recipeName+order) val description: String, // 步骤描述内容 val order: Int, // 步骤排序序号,保证步骤执行顺序正确 val recipeName: String // 关联Recipe的外键,和Recipe的主键字段完全匹配 )
小贴士:如果希望步骤和食谱的组合是唯一的,可以把主键改成复合主键(比如
@PrimaryKey(autoGenerate = false) val id: Pair<String, Int>),不过自增ID的方案也完全够用。
2. 创建包含两个列表的组合数据类
直接在你原来的RecipeWithKeyIngredients基础上扩展,新增一个steps列表,并用@Relation注解指定关联规则:
data class RecipeWithIngredientsAndSteps( @Embedded val recipe: Recipe, // 第一个关联:KeyIngredients列表(和你原来的实现一致) @Relation( parentColumn = "recipeName", entityColumn = "recipeName" ) val keyIngredients: List<KeyIngredients>, // 第二个关联:Steps列表 @Relation( parentColumn = "recipeName", entityColumn = "recipeName" ) val steps: List<Step> )
这里的核心逻辑是:每个@Relation注解都是独立的,Room会自动执行三次查询(一次查目标Recipe,两次分别查对应的KeyIngredients和Steps),然后把结果合并到这个组合类中,不需要你手动处理关联逻辑。
3. 在Dao层编写查询方法
和之前查询单个列表的逻辑一样,只需要把返回类型改成新的组合类,并且必须加上@Transaction注解(保证所有查询在同一个事务中执行,避免数据不一致):
@Dao interface RecipeDao { // 根据食谱名称查询单个食谱及其配料和步骤 @Transaction @Query("SELECT * FROM recipe WHERE recipeName = :recipeName") suspend fun getRecipeWithIngredientsAndSteps(recipeName: String): RecipeWithIngredientsAndSteps? // 查询所有食谱及其配料和步骤 @Transaction @Query("SELECT * FROM recipe") suspend fun getAllRecipesWithIngredientsAndSteps(): List<RecipeWithIngredientsAndSteps> }
一些注意事项
- 确保Step实体中的
recipeName字段,和Recipe实体的主键recipeName字段名、数据类型完全一致,否则关联会失败 - 如果你的Step实体有排序需求,记得在
@Relation里添加排序规则,比如:sort = [Sort(column = "order", direction = Sort.Direction.ASC)] - 插入测试数据时,要保证每个Step的
recipeName对应数据库中已存在的Recipe的名称
内容的提问来源于stack exchange,提问作者Bente61
相关产品推荐
相关产品推荐

