Android Room定义一对一关联构建报错:查询返回结果缺少对应列
问题根因
你当前的报错是因为Room框架的关联查询规则不匹配:
- 你在
DeviceAndRoom中用@Embedded注解标记了Room实体,这代表Room框架会默认将你执行的查询SQL返回的字段,映射到这个被@Embedded修饰的实体的所有属性上 - 你Dao中执行的是
SELECT * FROM Device,仅返回Device表的ipAddress、deviceName、type、uniqueRoomId四个字段,完全没有Room实体需要的roomId、name字段,因此直接触发字段缺失的报错
同时你当前的关联方向也和你的业务需求不匹配:你的业务是每个Device归属唯一Room,属于以Device为主体关联查询所属Room的场景,你当前写的关联逻辑是以Room为主体关联查询下属Device,方向是反的。
修复方案(适配你的业务需求)
1. 调整关联组合类的结构
将DeviceAndRoom的@Embedded改为修饰Device实体,调整@Relation的关联字段对应关系:
data class DeviceAndRoom( // 主实体改为Device,匹配你查询Device表的逻辑 @Embedded val device: Device, @Relation( parentColumn = "uniqueRoomId", // Device表中关联Room的外键 entityColumn = "roomId", // Room表的主键 entity = Room::class ) val room: Room )
2. (可选)添加唯一约束避免一对多数据异常
因为你的业务是一对一关联,为了避免出现一个Room对应多个Device的脏数据,可以在Device实体的类注解中添加唯一索引:
@Entity( indices = [Index(value = ["uniqueRoomId"], unique = true)] ) data class Device( @PrimaryKey(autoGenerate = false) val ipAddress: String, val deviceName: String, val type: Int, val uniqueRoomId: Int ) { @Ignore val status: DeviceStatus = DeviceStatus.Off }
3. Dao代码无需修改
你原来的Dao查询逻辑已经适配调整后的关联类,构建即可正常运行。
备选方案(如果你的需求是查询每个Room对应的Device)
如果你的业务实际是查询每个Room下的设备,不需要调整关联类结构,只需要修改Dao的查询SQL为主表查Room即可:
@Dao interface DeviceDao { @Transaction @Query("SELECT * FROM Room") // 改为查询Room表,提供@Embedded需要的roomId、name字段 fun getAllRoomAndDevices(): LiveData<List<DeviceAndRoom>> }
内容的提问来源于stack exchange,提问作者linux_lover
相关产品推荐
相关产品推荐

