HikariPool 达到最大连接数
HikariPool reaching maximum connection
我正在使用 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()
用于从数据库中的table获取数据。
这些函数如下所示:
// 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 的连接都会在最后关闭。
然而,池大小会一直增长,直到达到最大池大小并超时。
有什么方法可以防止这种情况或强制关闭连接?
按照@Nithin 的建议删除 preparedStatement.getConnection().close()
并在 try-with-resources 块中显式获取连接:
try (Connection con = SQLiteDataSource.getConnection();final PreparedStatement preparedStatement = con
// language=SQLite
.prepareStatement("SELECT " + column + " FROM table WHERE id = ?")) {
这样连接也会在块结束时关闭
您正在泄漏连接,因为您没有在 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 注入攻击。
我正在使用 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()
用于从数据库中的table获取数据。
这些函数如下所示:
// 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 的连接都会在最后关闭。 然而,池大小会一直增长,直到达到最大池大小并超时。
有什么方法可以防止这种情况或强制关闭连接?
按照@Nithin 的建议删除 preparedStatement.getConnection().close()
并在 try-with-resources 块中显式获取连接:
try (Connection con = SQLiteDataSource.getConnection();final PreparedStatement preparedStatement = con
// language=SQLite
.prepareStatement("SELECT " + column + " FROM table WHERE id = ?")) {
这样连接也会在块结束时关闭
您正在泄漏连接,因为您没有在 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 注入攻击。