Android Room Multimap返回类型下同名列_id的联表查询异常问题
问题说明
Room数据库官方优先推荐使用Multimap作为一对多关联查询的返回类型,但是当关联的两张表都使用_id作为主键列名时,会出现查询结果异常的问题。
对应实体类定义:
@Entity data class User(@PrimaryKey(autoGenerate = true) val _id: Long = 0, val name: String) @Entity data class Book(@PrimaryKey(autoGenerate = true) val _id: Long = 0, val bookName: String, val userId: Long)
Dao层查询代码:
@Query( "SELECT * FROM user " + "JOIN book ON user._id = book.userId" ) fun allUserBooks(): Flow<Map<User, List<Book>>>
该场景下,即使user表存在2条有效数据,最终返回的Map中也仅能得到1条条目。问题根源是Room生成Dao实现代码时,两张表的_id同名列会被分配相同的游标索引,导致实体属性映射错误。测试环境为Room 2.4.0-beta02版本。
无需中间数据类的解决方案
- 方案一:使用
@MapInfo注解区分列(推荐)
Room专门为Multimap返回类型提供了@MapInfo注解,通过指定key/value的列前缀即可区分同名列,无需修改实体类和表结构:
@Query( "SELECT u._id AS u__id, u.name AS u_name, b.* FROM user u JOIN book b ON u._id = b.userId" ) @MapInfo(keyColumnPrefix = "u_") // 声明Map的Key(User类)使用带u_前缀的列映射 fun allUserBooks(): Flow<Map<User, List<Book>>>
Room会自动将前缀匹配的列映射到对应实体,彻底避免同名列冲突。
- 方案二:修改实体主键列名
如果处于项目开发初期可调整表结构,可以给两个实体的主键指定不同的列名,原有查询语句无需修改即可正常运行:
@Entity data class User( @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "user_id") val _id: Long = 0, val name: String ) @Entity data class Book( @PrimaryKey(autoGenerate = true) @ColumnInfo(name = "book_id") val _id: Long = 0, val bookName: String, val userId: Long )
内容的提问来源于stack exchange,提问作者Goltsev Eugene
相关产品推荐
相关产品推荐

