Room框架中如何基于复合主键执行查询?
Room复合主键查询的正确实现方式
Room完全支持基于复合主键的查询,但你当前的写法存在问题——不能直接使用primaryKeys关键字作为查询条件,需要明确指定复合主键中的每个字段进行匹配。以下是两种正确的实现方案:
方案一:直接传入两个主键参数
直接将assetId和timestamp作为方法参数传入,在SQL语句中分别匹配这两个字段:
@Dao interface MarketCapDao { // 你的实体类定义(已存在) @Entity( tableName = "market_cap", primaryKeys = ["assetId", "timestamp"] ) data class MarketCapDataEntity( val assetId: String, val timestamp: Long, val price: Double ) // 正确的复合主键查询方法 @Query("SELECT * FROM market_cap WHERE assetId = :assetId AND timestamp = :timestamp") suspend fun getMarketCapByCompositeKey(assetId: String, timestamp: Long): MarketCapDataEntity? }
这种方式简单直接,适合不需要封装主键的场景,同时能精准匹配唯一的复合主键记录(因为复合主键组合是唯一的,返回单个实体而非列表更合理)。
方案二:封装复合主键为对象传入
如果希望将复合主键封装成一个独立的对象,可以定义一个数据类作为复合键载体,在SQL语句中通过对象属性访问字段:
// 定义复合主键封装类 data class MarketCapCompositeKey(val assetId: String, val timestamp: Long) @Dao interface MarketCapDao { @Query("SELECT * FROM market_cap WHERE assetId = :key.assetId AND timestamp = :key.timestamp") suspend fun getMarketCapByCompositeKey(key: MarketCapCompositeKey): MarketCapDataEntity? }
这种方式更符合面向对象的设计,当复合主键字段较多时,能简化方法参数的传递。
注意事项
- 复合主键的组合在表中是唯一的,所以查询结果通常是单个实体,将返回值定义为
MarketCapDataEntity?比List<MarketCapDataEntity>更贴合实际场景。 - 确保SQL语句中的字段名和实体类中的属性名完全一致,Room默认使用属性名映射数据库字段(除非用
@ColumnInfo指定了别名)。
内容的提问来源于stack exchange,提问作者Bitwise DEVS
相关产品推荐
相关产品推荐

