jOOQ fetch vs fetchResultSet 并在 Kotlin 中关闭连接
jOOQ fetch vs fetchResultSet and close connection in Kotlin
我将 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 中指定的方式工作:
This is the same as calling fetchLazy().resultSet()
and will return a ResultSet
wrapping the JDBC driver's ResultSet
. Closing this ResultSet may close the producing Statement
or PreparedStatement
, depending on your setting for 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)
}
}
注意,您不需要在 DSLContext
上调用 use()
方法。虽然 DSLContext
扩展了 AutoCloseable
,但仅当您的 DSLContext
管理基础 JDBC 连接(即创建它时)时才需要这样做。在您的情况下,当您将数据源传递给 DSL.using()
时,您不必关闭 DSLContext
.
我将 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 中指定的方式工作:
This is the same as calling
fetchLazy().resultSet()
and will return aResultSet
wrapping the JDBC driver'sResultSet
. Closing this ResultSet may close the producingStatement
orPreparedStatement
, depending on your setting forkeepStatement(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)
}
}
注意,您不需要在 DSLContext
上调用 use()
方法。虽然 DSLContext
扩展了 AutoCloseable
,但仅当您的 DSLContext
管理基础 JDBC 连接(即创建它时)时才需要这样做。在您的情况下,当您将数据源传递给 DSL.using()
时,您不必关闭 DSLContext
.