Android Room操作ExpRecord时不修改实体类获取分类名称的方法
Android Room 多表关联查询方案(无需在ExpRecord中添加冗余字段)
你不需要修改现有ExpRecord实体的字段定义,直接使用Room提供的关联查询注解即可实现需求,具体实现步骤如下:
- 定义关联查询组合数据类
新建普通数据类,通过@Embedded嵌入主表ExpRecord的字段,再通过@Relation注解配置和另外两张表的关联关系,Room会自动完成关联字段的映射。因为你配置了外键删除规则为SET_NULL,关联的分类、货币实体要声明为可空类型,避免关联数据被删除后查询崩溃:data class RecordWithExtendInfo( @Embedded val record: ExpRecord, @Relation( parentColumn = "expCategoryID", entityColumn = "id" ) val category: ExpCategory?, @Relation( parentColumn = "currencyID", entityColumn = "id" ) val currency: Currency? ) - 在DAO层编写关联查询方法
给查询方法加上@Transaction注解保证多表查询的原子性,直接返回上述组合数据类的类型即可,Room会自动完成多表关联查询逻辑,不需要手写JOIN语句:@Dao interface ExpRecordDao { @Transaction @Query("SELECT * FROM Record") fun getAllRecords(): Flow<List<RecordWithExtendInfo>> @Transaction @Query("SELECT * FROM Record WHERE date BETWEEN :startDate AND :endDate") fun getRecordsByDateRange(startDate: String, endDate: String): Flow<List<RecordWithExtendInfo>> } - 在ViewModel、Adapter中直接访问关联字段
ViewModel层直接从DAO层收集返回的Flow/LiveData数据即可,不需要额外做数据转换;Adapter绑定时直接读取对应字段:- 消费记录本身的金额、日期、备注:通过
item.record.amount、item.record.date、item.record.note访问 - 分类名称:通过
item.category?.name ?: "未分类"访问,加空值兜底适配分类被删除的场景 - 货币符号:通过
item.currency?.symbol ?: "¥"访问,同样做空值适配处理
- 消费记录本身的金额、日期、备注:通过
方案优势
- 无冗余字段:不需要在
ExpRecord表中额外存储分类名、货币符号,不会出现多表数据不一致的问题 - 自动映射:Room编译期自动生成关联查询代码,不需要手写字段映射逻辑,类型安全
- 实时同步:分类、货币表的信息更新后,查询消费记录时关联信息会自动同步,不需要额外更新Record表数据
内容的提问来源于stack exchange,提问作者ayah
相关产品推荐
相关产品推荐

