结果方法
本章介绍查询终端方法和结果形态。
查询结果方法
select 和 join 查询使用同一组终端方法。根据需要接收的结果形态选择方法。
投影字段和 alias 见 📚投影。命名分页结果见 📚排序、分页与聚合。
toMapList 返回 Map 列表
需要把每行作为 Map<String, Any?> 接收时,使用 toMapList();它等价于 toList<Map<String, Any?>>()。
kotlin
val rows: List<Map<String, Any?>> = User()
.select { [it.id, it.name] }
.where { it.age >= 18 }
.toMapList()Mysql
SELECT `id`, `name`
FROM `user`
WHERE `user`.`age` >= :ageMin返回结果是 Map 列表。
kotlin
listOf(
mapOf("id" to 1, "name" to "Ada"),
mapOf("id" to 2, "name" to "Grace")
)toList 返回类型列表
当查询列可以映射到目标类型时,使用 toList()。
kotlin
val users: List<User> = User()
.select()
.where { it.age >= 18 }
.toList()Mysql
SELECT `id`, `name`, `age`
FROM `user`
WHERE `user`.`age` >= :ageMin查询单列或自定义行类型时,显式传入泛型。
kotlin
val ids: List<Int> = User()
.select { it.id }
.toList<Int>()
val rows: List<UserSummary> = User()
.select { [it.id, it.name] }
.toList<UserSummary>()生成投影也可以直接作为返回类型使用。
kotlin
val rows = User()
.select { [it.id, f.length(it.name).alias("nameLength")] }
.toList()
val firstLength = rows.first().nameLength上面的无参调用返回编译器生成的投影类型。业务代码中需要命名 DTO 时,使用 select(UserSummary::class) { ... }。
dto
data class UserSummary(
var id: Int? = null,
var nameLength: Int? = null
) : KPojo
val summaries: List<UserSummary> = User()
.select(UserSummary::class) {
[it.id, f.length(it.name).alias("nameLength")]
}
.toList()投影 alias 规则和生成结果形态见 📚投影。
toMap 返回一条 Map
期望返回一行 Map 时,使用 toMap(),也可以写成 first<Map<String, Any?>>()。Kronos 会为查询加上 LIMIT 1。
kotlin
val row: Map<String, Any?> = User()
.select { [it.id, it.name] }
.where { it.id == 1 }
.toMap()Mysql
SELECT `id`, `name`
FROM `user`
WHERE `user`.`id` = :id
LIMIT 1toMap() 返回第一行 Map。
kotlin
mapOf("id" to 1, "name" to "Ada")toMapOrNull 返回可空 Map
查询结果为空也属于预期情况时,使用 toMapOrNull(),也可以写成 firstOrNull<Map<String, Any?>>() 或 first<Map<String, Any?>?>()。一般情况下,firstOrNull<T>() 等价于 first<T?>()。
kotlin
val row: Map<String, Any?>? = User()
.select { [it.id, it.name] }
.where { it.id == 404 }
.toMapOrNull()kotlin
nullfirst 返回一条类型结果
期望返回一行并映射到目标类型时,使用 first()。Kronos 会为查询加上 LIMIT 1。
kotlin
val user: User = User()
.select()
.where { it.id == 1 }
.first()Mysql
SELECT `id`, `name`, `age`
FROM `user`
WHERE `user`.`id` = :id
LIMIT 1查询单列或自定义行类型时,显式传入泛型。
kotlin
val name: String = User()
.select { it.name }
.where { it.id == 1 }
.first<String>()生成投影也可以用于单行结果方法。
kotlin
val row = User()
.select { [it.id, it.name.alias("username")] }
.where { it.id == 1 }
.first()
val username = row.username生成行可以像一个小结果对象一样使用,属性来自选中的字段和 alias。
firstOrNull 返回可空类型结果
查询结果为空时需要返回 null,使用 firstOrNull()。
kotlin
val user: User? = User()
.select()
.where { it.id == 404 }
.firstOrNull()kotlin
nullkotlin
data class UserRow(
val id: Int?,
val displayName: String?
)
val query = User()
.select { [it.id, it.name.alias("displayName")] }
.where { it.age >= 18 }
val users: List<UserRow> = query.toList<UserRow> { row ->
UserRow(
id = row.get<Int?>(1),
displayName = row.get<String?>("displayName")
)
}
val first: UserRow = query.first<UserRow> { row ->
UserRow(row.get<Int?>("id"), row.get<String?>("displayName"))
}
val missing: UserRow? = query.firstOrNull<UserRow> { row ->
UserRow(row.get<Int?>("id"), row.get<String?>("displayName"))
}row.get<T>("label") 按列名或 alias 读取,row.get<T>(field) 使用 Field 的投影输出名,名称为空时回退到数据库列名,row.get<T>(position) 按 JDBC 列位置读取,位置从 1 开始;值按目标 KType 经过当前结果映射和 ValueCodec 转换。rowNumber 从 0 开始,row 在映射回调执行期间有效。KronosJdbcWrapper 支持该行映射能力。
在 join 后使用结果方法
Join 查询使用和 select 相同的结果方法。
kotlin
val rows: List<UserOrderRow> = User().join(Order()) { user, order ->
leftJoin { user.id == order.userId }
.select { [user.id, user.name, order.status] }
}.toList<UserOrderRow>()Mysql
SELECT `user`.`id`, `user`.`name`, `order`.`status`
FROM `user`
LEFT JOIN `order`
ON `user`.`id` = `order`.`user_id`在分页后使用结果方法
page(pageIndex, pageSize).toList() 直接返回当前页记录。需要总数时,在 page(...) 后调用 withTotal(),得到包含命名元数据的 PageResult<T>。
kotlin
val mapPage: PageResult<Map<String, Any?>> = User()
.select { [it.id, it.name] }
.page(1, 20)
.withTotal()
.toMapList()
val typedPage: PageResult<User> = User()
.select()
.page(1, 20)
.withTotal()
.toList()
val users = typedPage.records
val total = typedPage.total游标执行返回 CursorResult<T>,包含 hasNext、nextCursor 和 records。
kotlin
val cursorPage: CursorResult<User> = User()
.select()
.orderBy { it.id.asc() }
.cursor(pageSize = 20)
.toList()使用指定数据源
当本次查询需要使用指定数据源时,把 KronosDataSourceWrapper 传给任意终端方法。
kotlin
val customWrapper = CustomWrapper()
val users: List<User> = User()
.select()
.where { it.age >= 18 }
.toList(customWrapper)Wrapper 配置见 📚Kronos Data Source Wrapper。