使用Exposed查询单条数据时select lambda报错的问题排查
Exposed 0.60.0 查询单条CarModel数据的类型不匹配问题解析
第一种写法类型不匹配的原因
你遇到的「Type mismatch. Required: List<Expression<*>> Found: () → Op」错误,核心原因是Kotlin编译器的重载解析优先级问题:
- Exposed 0.60.0的
Table.select()方法有两个关键重载:select(vararg columns: Expression<*>):用于指定要查询的列,参数是列表达式的可变参数select(where: (ColumnSet) -> Op<Boolean>):用于传递查询条件lambda
- 当你直接写
CarModels.select { CarModels.id eq carModelId }时,编译器会优先匹配第一个重载(接收列列表的版本),把你的查询条件lambda错误识别为返回Expression<*>的函数,但你的lambda实际返回的是Op<Boolean>类型的条件表达式,因此触发类型不匹配错误。
关于第二个「id is not in record set」异常的补充
你调整写法后出现的这个异常,通常是因为查询结果的行中没有包含id列:
- 如果你调整写法时不小心指定了具体查询列(比如
select(CarModels.brand, CarModels.model) { ... }),但后续又尝试从行中获取CarModels.id,就会触发这个错误; - 另外,如果查询本身没有匹配到任何数据,强行访问行中的列也可能出现类似问题,但报错信息会更明确指向空行。
修正后的正确写法
要解决类型不匹配问题,只需要明确指定select方法的where参数,让编译器匹配正确的重载:
override suspend fun getCarModel(carModelId: Int): CarModel? { return transaction { addLogger(StdOutSqlLogger) CarModels .select(where = { CarModels.id eq carModelId }) // 明确指定where参数 .mapNotNull { row -> CarModel( id = row[CarModels.id], brand = row[CarModels.brand], model = row[CarModels.model], year = row[CarModels.year] ) }.singleOrNull() } }
或者你也可以使用find方法来简化单条数据查询,代码更简洁:
override suspend fun getCarModel(carModelId: Int): CarModel? { return transaction { addLogger(StdOutSqlLogger) CarModels.find { CarModels.id eq carModelId } .mapNotNull { row -> CarModel( id = row[CarModels.id], brand = row[CarModels.brand], model = row[CarModels.model], year = row[CarModels.year] ) }.singleOrNull() } }
内容的提问来源于stack exchange,提问作者Andrei Rusu
相关产品推荐
相关产品推荐

