Reputation: 7719
I'm using Kotlin with the kotliquery jdbc framework
Just ran into a problem. I'm using a remote PostgreSQL database. After a bit of calling the database I get the following error Failure: too many clients already
. Which is caused by 100 connections being idle
.
I'm trying to create 1 point where I have to do the config. This is what I call my BaseDAO. The relevant code for that class looks like this:
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())
}
}
}
And one of my DAO's:
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
}
}
After looking into Kotliquery's source code I realized the session.connection.close()
and session.close
wouldn't even be neccessary when using using
(since it closes a closable
which the retrieved session
is.) but without them I got the same error. (had to restart postgresql database -- 100 idle connections).
I was wondering if there is an error in my code or if this is an error in Kotliquery?
(also submitted github issue #6 but figured the community might be bigger than 24 people
Upvotes: 1
Views: 534
Reputation: 41648
It seems that each call to BaseDAO.getSession()
creates new HikariDataSource
. This means that every Session
has effectively it's own database connection pool. To resolve that you need to maintain instance of HikariDataSource
differently i.e.:
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)
}
}
}
Upvotes: 1