Android Room一对多关系查询:如何筛选指定日期范围的关联Child实体?
可以实现,共有三种常用的实现方案,可根据你的Room版本和业务需求选择:
方案1:使用@Relation的filterExpression属性(推荐,Room 2.4.0+支持)
这是最简单的实现方式,Room会自动帮你过滤关联的Child实体:
- 确保你的Room依赖版本不低于2.4.0
- 修改Combined类的@Relation注解,添加过滤条件:
data class Combined( @Embedded val parent: Parent, @Relation( parentColumn = "elementId", entityColumn = "Id", // date为Child表存储日期的字段名,参数自动匹配DAO方法的入参 filterExpression = "date BETWEEN :startDate AND :endDate" ) val children: List<Child> )
- 新增DAO查询方法,传入日期范围参数:
@Transaction @Query("SELECT * FROM Parent") fun getCombinedWithChildrenInDateRange(startDate: Instant, endDate: Instant): Flow<List<Combined>>
该方案会返回所有Parent实体,无符合条件Child的Parent对应的children字段为空列表。
方案2:配合JOIN查询过滤Parent实体
如果你的业务要求只返回至少存在一个符合日期范围Child的Parent,可以修改查询语句为关联查询,配合方案1的filterExpression使用,即可同时过滤Parent和对应的Child列表:
@Transaction @Query(""" SELECT DISTINCT Parent.* FROM Parent INNER JOIN Child ON Parent.elementId = Child.Id WHERE Child.date BETWEEN :startDate AND :endDate """) fun getCombinedWithChildrenInDateRange(startDate: Instant, endDate: Instant): Flow<List<Combined>>
方案3:手动组装数据(兼容低版本Room)
如果你的Room版本低于2.4.0,没有filterExpression属性,可以在仓库层手动组装结果:
- DAO层新增两个基础查询方法:
// 查询指定日期范围内的所有Child @Query("SELECT * FROM Child WHERE date BETWEEN :startDate AND :endDate") suspend fun getChildrenInDateRange(startDate: Instant, endDate: Instant): List<Child> // 批量查询指定ID的Parent @Query("SELECT * FROM Parent WHERE elementId IN (:parentIds)") suspend fun getParentsByIds(parentIds: List<Long>): List<Parent>
- 仓库层组装Combined数据:
suspend fun getCombinedInDateRange(startDate: Instant, endDate: Instant): List<Combined> { val matchedChildren = getChildrenInDateRange(startDate, endDate) val parentIds = matchedChildren.map { it.Id }.distinct() val matchedParents = getParentsByIds(parentIds) val childrenGroup = matchedChildren.groupBy { it.Id } return matchedParents.map { parent -> Combined( parent = parent, children = childrenGroup[parent.elementId].orEmpty() ) } }
注意事项
- 提前给Child表的date字段添加索引,避免大数据量下查询性能过低。
- 你需要提前配置好Instant和Long类型的Room类型转换器,确保入参和表中存储的时间戳可以自动转换。
内容的提问来源于stack exchange,提问作者shko
相关产品推荐
相关产品推荐

