You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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属性,可以在仓库层手动组装结果:

  1. 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>
  1. 仓库层组装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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.10 08:42:02