HikariCP 未在 close() 上关闭连接(连接泄漏)
HikariCP not closing connections on close() (Connection Leak)
我正在使用 HikariCP 3.3.1 和 PostgreSQL。但是我在关闭连接时遇到问题,在 Hikari 配置中我将最大池大小设置为 15,将最小空闲连接设置为 5,但是在使用数据库几分钟后我发现连接没有关闭,它们堆叠越来越多(现在将近 100 个空闲连接)。
我的连接器class:
Connector.java
public class Connector implements IConnector {
private static HikariConfig config = new HikariConfig();
private static HikariDataSource ds;
static {
config.setDriverClassName(org.postgresql.Driver.class.getName());
config.setJdbcUrl("jdbc:postgresql://localhost:5432/vskDB");
config.setUsername("postgres");
config.setPassword("root");
config.setMinimumIdle(5);
config.setMaximumPoolSize(15);
config.setConnectionTimeout(20000);
config.setIdleTimeout(300000);
ds = new HikariDataSource(config);
}
public Connection getConnection() {
log.info("getConnection() invoked");
try {
return ds.getConnection();
} catch (SQLException e) {
log.error("Can't get connection from DataSource.");
log.error(e.getMessage());
System.out.println(e.getMessage());
}
return null;
}
Connector() {
}
}
这是我的 DAO class(已简化):
UserDAO.java
public class UserDatabaseDAO implements UserDAO {
private Connector connector = new Connector();
private Connection dbConnection;
@Override
public void removeUser(Long id) {
try {
dbConnection = connector.getConnection();
if (dbConnection == null)
throw new ConnectException();
PreparedStatement preparedStatement = dbConnection.prepareStatement("DELETE FROM users WHERE user_id = ?");
preparedStatement.setLong(1, id);
preparedStatement.execute();
} catch (SQLException | ConnectException e) {
log.error("Can't remove user from database");
log.error(e.getMessage());
System.out.print(e.getMessage());
} finally {
try {
dbConnection.close();
} catch (SQLException e) {
log.error("Can't close connection");
log.error(e.getMessage());
System.out.print(e.getMessage());
}
}
}
}
Here 我发现关于 Hikari 的一些事实存在问题:
你必须在 HikariCP 给你的连接实例上调用 close()
也许我的 dbConnection.close()
不会工作,因为它只是 Hikari 在 getConnection()
方法中给我的 Connection 的副本。
你也忘记关闭了PreparedStatement
try {
if (preparedStatement != null) {
preparedStatement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
Releases this Statement object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed. It is generally good practice to release resources as soon as you are finished with them to avoid tying up database resources.
我正在使用 HikariCP 3.3.1 和 PostgreSQL。但是我在关闭连接时遇到问题,在 Hikari 配置中我将最大池大小设置为 15,将最小空闲连接设置为 5,但是在使用数据库几分钟后我发现连接没有关闭,它们堆叠越来越多(现在将近 100 个空闲连接)。
我的连接器class:
Connector.java
public class Connector implements IConnector {
private static HikariConfig config = new HikariConfig();
private static HikariDataSource ds;
static {
config.setDriverClassName(org.postgresql.Driver.class.getName());
config.setJdbcUrl("jdbc:postgresql://localhost:5432/vskDB");
config.setUsername("postgres");
config.setPassword("root");
config.setMinimumIdle(5);
config.setMaximumPoolSize(15);
config.setConnectionTimeout(20000);
config.setIdleTimeout(300000);
ds = new HikariDataSource(config);
}
public Connection getConnection() {
log.info("getConnection() invoked");
try {
return ds.getConnection();
} catch (SQLException e) {
log.error("Can't get connection from DataSource.");
log.error(e.getMessage());
System.out.println(e.getMessage());
}
return null;
}
Connector() {
}
}
这是我的 DAO class(已简化): UserDAO.java
public class UserDatabaseDAO implements UserDAO {
private Connector connector = new Connector();
private Connection dbConnection;
@Override
public void removeUser(Long id) {
try {
dbConnection = connector.getConnection();
if (dbConnection == null)
throw new ConnectException();
PreparedStatement preparedStatement = dbConnection.prepareStatement("DELETE FROM users WHERE user_id = ?");
preparedStatement.setLong(1, id);
preparedStatement.execute();
} catch (SQLException | ConnectException e) {
log.error("Can't remove user from database");
log.error(e.getMessage());
System.out.print(e.getMessage());
} finally {
try {
dbConnection.close();
} catch (SQLException e) {
log.error("Can't close connection");
log.error(e.getMessage());
System.out.print(e.getMessage());
}
}
}
}
Here 我发现关于 Hikari 的一些事实存在问题:
你必须在 HikariCP 给你的连接实例上调用 close()
也许我的 dbConnection.close()
不会工作,因为它只是 Hikari 在 getConnection()
方法中给我的 Connection 的副本。
你也忘记关闭了PreparedStatement
try {
if (preparedStatement != null) {
preparedStatement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
Releases this Statement object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed. It is generally good practice to release resources as soon as you are finished with them to avoid tying up database resources.