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

Room关联查询返回Circuit对象id错误问题排查咨询

问题成因及解决方案

成因分析

核心问题是同名列冲突导致的Room映射错误:

  • circuits表的主键是id,而circuit_sessions表大概率也定义了id作为自身的主键字段。
  • 执行SELECT *时,查询结果会同时包含两张表的id列。Room默认按字段名匹配列值,此时会误将circuit_sessions表的id值(恰好为1)赋值给Circuit实体的id字段,而非预期的circuits.id。
  • App Inspection能显示正确结果,是因为它会明确标注列的所属表,不会混淆同名列,但Room的默认映射逻辑不处理这种冲突。

解决方法

方法1:明确指定查询列并给目标列起别名

修改DAO的查询语句,只选取circuits表的字段,确保id列的唯一性:

@Query("SELECT circuits.id AS id, circuits.name, circuits.[其他需要的字段] FROM circuits INNER JOIN circuit_sessions ON circuits.id = circuit_sessions.circuitId WHERE circuit_sessions.driverId = :driverId ORDER BY name ASC")

需将circuits表的所有业务字段逐一列出,通过AS id确保circuits.id准确映射到Circuit的id属性。

方法2:用@ColumnInfo指定列映射规则

在Circuit实体的id字段上添加注解,明确指定要映射的列(带表名前缀):

@Entity(tableName = "circuits")
data class Circuit(
    @PrimaryKey
    @ColumnInfo(name = "circuits_id")
    val id: Int,
    // 其他字段定义...
)

同时修改查询语句,给circuits.id起对应别名:

@Query("SELECT circuits.id AS circuits_id, circuits.* FROM circuits INNER JOIN circuit_sessions ON circuits.id = circuit_sessions.circuitId WHERE circuit_sessions.driverId = :driverId ORDER BY name ASC")

这种方式可以保留SELECT circuits.*的写法,避免逐个列名的繁琐。

方法3:使用嵌入实体的POJO接收结果

创建专用POJO类,通过@Embedded指定只映射Circuit的字段:

data class CircuitForDriver(
    @Embedded val circuit: Circuit
)

然后修改DAO的返回类型为List<CircuitForDriver>,查询语句调整为:

@Query("SELECT circuits.* FROM circuits INNER JOIN circuit_sessions ON circuits.id = circuit_sessions.circuitId WHERE circuit_sessions.driverId = :driverId ORDER BY name ASC")

这种方式让Room只处理circuits表的字段,从根源避免列名冲突。


内容的提问来源于stack exchange,提问作者Geshode

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:42:27