How do I use connection pooling in JDBC with HikariCP?

To use connection pooling in plain JDBC with HikariCP, the main shift is:

  • stop using DriverManager.getConnection(...) everywhere
  • create one DataSource (the pool) at startup
  • whenever you need a DB connection, call dataSource.getConnection()
  • always close resources with try-with-resources (closing returns the connection to the pool, it does not kill the physical connection)

1) Create a pooled DataSource once

A simple “factory” that builds a singleton pool:

package org.kodejava.jdbc;

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;

import javax.sql.DataSource;
import java.time.Duration;

public final class DataSourceFactory {
    private static final HikariDataSource dataSource = create();

    private DataSourceFactory() {}

    private static HikariDataSource create() {
        HikariConfig config = new HikariConfig();

        config.setJdbcUrl("jdbc:postgresql://localhost:5432/app_db");
        config.setUsername("db_user");
        config.setPassword("db_password"); // use env vars/secret store in real apps

        // Pool sizing (tune per app + DB limits)
        config.setMaximumPoolSize(10);
        config.setMinimumIdle(2);

        // Timeouts
        config.setConnectionTimeout(Duration.ofSeconds(5).toMillis()); // wait for a connection from pool
        config.setIdleTimeout(Duration.ofMinutes(5).toMillis());
        config.setMaxLifetime(Duration.ofMinutes(30).toMillis());

        // Optional: validation / observability
        config.setPoolName("AppHikariPool");

        return new HikariDataSource(config);
    }

    public static DataSource getDataSource() {
        return dataSource;
    }

    /** Call this on application shutdown */
    public static void shutdown() {
        dataSource.close();
    }
}

Notes:

  • maximumPoolSize is usually the most important setting.
  • Prefer one pool per database, not one per DAO/class.

2) Use it in JDBC code (and always close)

Example query using the pooled DataSource:

package org.kodejava.jdbc;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class UserRepository {
    private final DataSource dataSource;

    public UserRepository(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public String findEmailById(long id) throws SQLException {
        String sql = "select email from users where id = ?";

        try (Connection con = dataSource.getConnection();
             PreparedStatement ps = con.prepareStatement(sql)) {

            ps.setLong(1, id);

            try (ResultSet rs = ps.executeQuery()) {
                return rs.next() ? rs.getString("email") : null;
            }
        }
    }
}

Key point: con.close() (done by try-with-resources) returns the connection to the pool.


3) Shutdown cleanly

If you’re writing a CLI app / desktop app / simple server, ensure the pool is closed on exit:

package org.kodejava.jdbc;

public class App {
    public static void main(String[] args) throws Exception {
        var ds = DataSourceFactory.getDataSource();
        var repo = new UserRepository(ds);

        System.out.println(repo.findEmailById(1L));

        DataSourceFactory.shutdown();
    }
}

For long-running apps, register a shutdown hook:

Runtime.getRuntime().addShutdownHook(new Thread(DataSourceFactory::shutdown));

4) Common configuration tips (practical)

  • Pool size: start with maximumPoolSize=10 for typical web apps, then tune using metrics and DB limits.
  • Don’t set minimumIdle too high unless you truly need warm connections.
  • Transactions: still work the same (use con.setAutoCommit(false) and commit/rollback), but make sure you always return the connection to the pool.
  • If you see “connection leak” warnings, it usually means some path didn’t close the connection (missing try-with-resources).

Maven dependencies

<dependencies>
  <dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>6.3.0</version>
  </dependency>

  <dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.7.7</version>
  </dependency>
</dependencies>

Maven Central Maven Central

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.