HikariPool достигает максимального соединения - PullRequest
0 голосов
/ 12 апреля 2020

Я использую HikariCP для запуска базы данных SQLite. Моя конфигурация выглядит так:

public class SQLiteDataSource {
    private static final HikariConfig config = new HikariConfig();
    private static final HikariDataSource ds;

    static {


        config.setJdbcUrl("jdbc:sqlite:database.db");
        config.setConnectionTestQuery("SELECT 1");
        config.addDataSourceProperty("cachePrepStmts", true);
        config.addDataSourceProperty("prepStmtCacheSize", "250");
        config.addDataSourceProperty("prepStmtCacheSwlLimit", "2048");
        config.setIdleTimeout(10000);
        config.setMaxLifetime(30000);
        config.setValidationTimeout(30000);
        config.setMaximumPoolSize(100);
        config.setMinimumIdle(10);
        config.setAllowPoolSuspension(false);

        ds = new HikariDataSource(config);
    }

    public static Connection getConnection() throws SQLException {
        return ds.getConnection();
    }
}

Метод getConnection() используется для получения данных из таблицы в базе данных. Эти функции выглядят так:

// This is a slightly abreviated function to get a boolean from a table in the database where the primary key "id" matches the one requested

 public static Boolean getBoolean(String Id, String column) {
        try (final PreparedStatement preparedStatement = SQLiteDataSource.getConnection()
                // language=SQLite
                .prepareStatement("SELECT " + column + " FROM table WHERE id = ?")) {

            preparedStatement.setString(1, Id);

            try (final ResultSet resultSet = preparedStatement.executeQuery()) {
                if (resultSet.next()) {
                    Boolean bool = resultSet.getBoolean(setting);
                    resultSet.close();
                    preparedStatement.getConnection().close();
                    return bool;
                }
            }

            preparedStatement.getConnection().close();

        } catch (SQLException e) {
        e.printStackTrace();
        }
        return false;
    }

Каждый раз, когда вызывается функция, соединение PreparedStatement закрывается в конце. Однако размер пула продолжает расти, пока не достигнет максимального размера пула и не истечет время ожидания.

Есть ли способ предотвратить это или принудительно отключить соединения?

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

Вы теряете соединение, потому что у вас нет ссылки в блоке try-with-resources . В результате соединение, которое вы использовали для создания оператора, никогда не закрывается. Вместо этого вы получаете другое соединение и закрываете его (в двух разных точках!). В конечном итоге вы исчерпаете пул соединений таким образом.

Кроме того, поскольку вы используете try-with-resources, вам не нужно явно закрывать resultSet.

. измените свой код на:

try (Connection connection = SQLiteDataSource.getConnection();
     PreparedStatement preparedStatement = connection
            .prepareStatement("SELECT " + column + " FROM table WHERE id = ?")) {

    preparedStatement.setString(1, Id);

    try (ResultSet resultSet = preparedStatement.executeQuery()) {
        if (resultSet.next()) {
            Boolean bool = resultSet.getBoolean(setting);
            return bool;
        }
    }
} catch (SQLException e) {
    e.printStackTrace();
}

Также имейте в виду, что если значение column из ненадежного источника, вы уязвимы для SQL инъекции.

1 голос
/ 12 апреля 2020

Удалить preparedStatement.getConnection().close(), как предложил @Nithin, а также получить соединение явно в блоке try-with-resources:

try (Connection con = SQLiteDataSource.getConnection();final PreparedStatement preparedStatement = con
                // language=SQLite
                .prepareStatement("SELECT " + column + " FROM table WHERE id = ?")) {

Таким образом, соединение будет также закрыто в конце блока

...