Room数据库JOIN查询疑问:Dao存放位置与返回类设计
解决Room中JOIN查询的困惑:一步步帮你理清
嘿,别慌!作为Room新手,遇到跨表查询的问题太正常了,我来帮你把思路理顺,分几步解决你的疑问:
1. 必须创建一个专门的返回类
Room需要明确知道查询结果要映射到哪个对象,所以你得创建一个数据类来承载联合查询的字段。这个类不需要加@Entity注解,只需要包含你想要的字段就行,注意字段名要和查询语句里的列名一致(或者用@ColumnInfo指定对应关系)。
举个例子,你可以命名为MedicationWithReminder:
data class MedicationWithReminder( val name: String, val mg: Int, // 根据你实际的字段类型调整,比如如果是Float就改Float val hour: Int, val minutes: Int, val amountOfDoses: Int, val dayToRemind: String // 假设是存储星期几的字符串,比如"Monday" )
2. 先补全表之间的关联关系
哦对了,你现在的两个表没有关联条件!JOIN查询需要两个表之间有外键关联,不然数据库不知道怎么把Medication和Reminder对应起来。所以你需要给Reminder实体添加一个med_id字段,作为关联Medication表的外键:
@Entity( foreignKeys = [ForeignKey( entity = Medication::class, parentColumns = ["med_id"], childColumns = ["med_id"], onDelete = ForeignKey.CASCADE // 可选,当Medication被删除时自动删除关联的Reminder )] ) data class Reminder( @PrimaryKey val reminder_id: Int, val hour: Int, val minutes: Int, val amountOfDoses: Int, val dayToRemind: String, val med_id: Int // 新增外键,关联Medication的med_id )
3. Dao的选择:灵活但推荐职责单一
关于查询放在哪个Dao里,没有严格的强制规定,但从代码整洁和职责分离的角度来说,我推荐你创建一个单独的Dao,比如MedicationReminderDao,专门处理跨表的联合查询。当然,如果你的业务逻辑更偏向从Medication出发关联Reminder,放在MedicationDao里也完全没问题——怎么方便怎么来。
下面是在MedicationReminderDao里写的JOIN查询示例:
@Dao interface MedicationReminderDao { // 查询所有Medication关联的Reminder数据 @Query(""" SELECT m.name, m.mg, r.hour, r.minutes, r.amountOfDoses, r.dayToRemind FROM Medication m INNER JOIN Reminder r ON m.med_id = r.med_id """) fun getAllMedicationWithReminders(): List<MedicationWithReminder> // 按med_id查询特定药物的提醒数据 @Query(""" SELECT m.name, m.mg, r.hour, r.minutes, r.amountOfDoses, r.dayToRemind FROM Medication m INNER JOIN Reminder r ON m.med_id = r.med_id WHERE m.med_id = :medId """) fun getMedicationWithRemindersByMedId(medId: Int): List<MedicationWithReminder> }
最后总结一下步骤
- 给Reminder表添加外键字段,建立和Medication的关联;
- 创建承载联合结果的数据类;
- 在合适的Dao中编写JOIN查询,返回这个数据类的List。
这样操作下来,你就能得到想要的联合数据列表啦!
内容的提问来源于stack exchange,提问作者Lian Binyamin
相关产品推荐
相关产品推荐

