【问题标题】:jOOQ fetch vs fetchResultSet and close connection in KotlinjOOQ fetch vs fetchResultSet 并在 Kotlin 中关闭连接
【发布时间】:2019-08-15 11:25:54
【问题描述】:

我正在使用 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()
        }
    }
}

这是我应该使用的最后一种方法吗?

【问题讨论】:

  • 为什么首先要获取 JDBC ResultSet?您的代码并未暗示这对您有用。还有,为什么每次都返回emptyList()
  • @LukasEder 好吧,是的,也许这不是最明确的例子,只是想快速显示我的问题,对此感到抱歉。我需要ResultSet,因为那时我使用SimpleFlatMapper 生成具有多对多关系的结果,如本文arnaudroger.github.io/blog/2017/02/27/jooq-one-to-many.html 中所述,类似于MyClass.mapper.stream(rs).toList()(映射器位于MyClass 的伴随对象中)。让我更新一下问题。
  • 嗯,也许,与其更新问题(因为我的回答仍然对其他人有用),你能问一个更完整的新问题吗?以下是一些指导方针:stackoverflow.com/help/mcve

标签: kotlin jooq hikaricp


【解决方案1】:

它的工作原理与Javadoc 中指定的完全相同:

这与调用fetchLazy().resultSet() 相同,将返回一个包装JDBC 驱动程序ResultSetResultSet。关闭此 ResultSet 可能会关闭生成 StatementPreparedStatement,具体取决于您对 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

【讨论】:

    猜你喜欢
    • 2019-08-15
    • 2014-02-19
    • 1970-01-01
    • 2021-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    相关资源
    最近更新 更多