Kotliquery不关闭postgresql连接

时间:2016-10-26 09:01:27

标签: postgresql jdbc kotlin hikaricp

我正在使用Kotlin和kotliquery jdbc框架

刚遇到问题。我正在使用远程PostgreSQL数据库。在调用数据库之后,我收到以下错误Failure: too many clients already。这是由100个连接idle引起的。

我正在尝试创建1点,我必须进行配置。这就是我所说的BaseDAO。该类的相关代码如下所示:

import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import kotliquery.Session
import kotliquery.sessionOf
import javax.sql.DataSource

class BaseDAO {
    companion object {
        var url: String = "jdbc:postgresql://server.local:5432/myDatabase"
        var user: String = "postgres"
        var pass: String = "postgres"

        val config: HikariConfig = HikariConfig()

        private fun dataSource(): DataSource
        {
            var hikariConfig: HikariConfig =  HikariConfig();
            hikariConfig.setDriverClassName("org.postgresql.Driver");
            hikariConfig.setJdbcUrl(url);
            hikariConfig.setUsername(user);
            hikariConfig.setPassword(pass);

            hikariConfig.setMaximumPoolSize(5);
            hikariConfig.setConnectionTestQuery("SELECT 1");
            hikariConfig.setPoolName("springHikariCP");

            hikariConfig.addDataSourceProperty("dataSource.cachePrepStmts", "true");
            hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSize", "250");
            hikariConfig.addDataSourceProperty("dataSource.prepStmtCacheSqlLimit", "2048");
            hikariConfig.addDataSourceProperty("dataSource.useServerPrepStmts", "true");

            var dataSource: HikariDataSource  = HikariDataSource(hikariConfig);

            return dataSource;
        }

        @JvmStatic fun getSession(): Session {
            return sessionOf(dataSource())
        }
    }

}

我的一个DAO:

class UserDAO {

    val toUser: (Row) -> User = { row ->
        User(
                row.int("id"),
                row.string("username"),
                row.string("usertype")
        )
    }

    fun getAllUsers(): List<User> {
        var returnedList: List<User> = arrayOf<User>().toList()
        using(BaseDAO.getSession()) { session ->

            val allUsersQuery = queryOf("select * from quintor_user").map(toUser).asList
            returnedList = session.run(allUsersQuery)
            session.connection.close() 
            session.close()
        }

        return returnedList
    }
}

在查看Kotliquery的源代码后,我意识到session.connection.close()session.close在使用using时甚至不是必需的(因为它关闭了closable所获得的session {1}}是。)但没有它们我得到了同样的错误。 (不得不重新启动postgresql数据库--100个空闲连接)。

我想知道我的代码中是否有错误,或者这是Kotliquery中的错误?

(也提交了github问题#6,但认为社区可能超过24人

1 个答案:

答案 0 :(得分:1)

似乎每次调用BaseDAO.getSession()都会创建新的HikariDataSource。这意味着每个Session都有效地拥有自己的数据库连接池。要解决此问题,您需要不同地维护HikariDataSource的实例,例如:

class BaseDAO {
    companion object {
        ...
        private val dataSource by lazy {
            var hikariConfig: HikariConfig =  HikariConfig();
            ...
            var dataSource: HikariDataSource  = HikariDataSource(hikariConfig);

            dataSource;
        }

        @JvmStatic fun getSession(): Session {
            return sessionOf(dataSource)
        }
    }

}