我正在使用Kotlin和HikariCP和jOOQ来查询我的数据库。我已经意识到这段代码按预期工作,然后获取行并关闭连接:
class CountriesService(private val datasource: DataSource) {
private val countries = Countries()
fun getCountries(): List<String> {
DSL.using(datasource, SQLDialect.POSTGRES_10)
.use { ctx ->
ctx.select(countries.CO_NAME)
.from(countries)
.orderBy(countries.CO_NAME)
.fetch()
return emptyList()
}
}
}
而如果我使用fetchResultSet()
,连接永远不会关闭,游泳池会变干:
class CountriesService(private val datasource: DataSource) {
private val countries = Countries()
fun getCountries(): List<String> {
DSL.using(datasource, SQLDialect.POSTGRES_10)
.use { ctx ->
ctx.select(countries.CO_NAME)
.from(countries)
.orderBy(countries.CO_NAME)
.fetchResultSet()
return emptyList()
}
}
}
我已经看到AbstractResultQuery#fetchResultSet()
委托给fetchLazy()
方法,因此不确定它是否与此有关。
如果我自己获得连接而不是将其委托给DSLContext
,那么它可以工作:
class CountriesService(private val datasource: DataSource) {
private val countries = Countries()
fun getCountries(): List<String> {
val conn = datasource.connection
conn.use {
DSL.using(it, SQLDialect.POSTGRES_10)
.select(countries.CO_NAME)
.from(countries)
.orderBy(countries.CO_NAME)
.fetchResultSet()
return emptyList()
}
}
}
这是我应该使用的最后一种方法吗?
它完全按照Javadoc中的规定工作:
这与调用
fetchLazy().resultSet()
相同,并将返回包含JDBC驱动程序的ResultSet
的ResultSet
。关闭此ResultSet可能会关闭生成的Statement
或PreparedStatement
,具体取决于您对keepStatement(boolean)
的设置。
这个方法的要点是你想要使用JDBC结果集而不是让jOOQ为你消耗它。所以,你负责资源管理。
鉴于您的示例代码,您绝对不应该调用此方法,而是调用fetch()
。例如:
class CountriesService(private val datasource: DataSource) {
private val countries = Countries()
fun getCountries(): List<String> {
return
DSL.using(datasource, SQLDialect.POSTGRES_10)
.select(countries.CO_NAME)
.from(countries)
.orderBy(countries.CO_NAME)
.fetch(countries.CO_NAME)
}
}
请注意,您不需要在use()
上调用DSLContext
方法。虽然DSLContext
扩展了AutoCloseable
,但只有当你的DSLContext
管理底层JDBC连接时(即它创建它时),才需要这样做。在您的情况下,当您将数据源传递给DSL.using()
时,您不必关闭DSLContext
。