gpt4 book ai didi

java - JDBC MySql连接池实践避免连接池耗尽

转载 作者:IT王子 更新时间:2023-10-29 00:31:32 26 4
gpt4 key购买 nike

我在 GlassFish 上有一个 Java-JSF Web 应用程序,我想在其中使用连接池。因此,我创建了一个 application 范围的 bean,它与其他 bean 的 Connection 实例一起服务:

public class DatabaseBean {

private DataSource myDataSource;

public DatabaseBean() {
try {
Context ctx = new InitialContext();
ecwinsDataSource = (DataSource) ctx.lookup("jdbc/myDataSource");
} catch (NamingException ex) {
ex.printStackTrace();
}
}

public Connection getConnection() throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException {
Connection connection = myDataSource.getConnection();
System.out.println("Succesfully connected: " + connection);
//Sample: Succesfully connected: com.sun.gjc.spi.jdbc40.ConnectionHolder40@7fb213a5
return connection;
}
}

这样连接池就会很快被填满;在“数据库相关” View 中进行几次导航后,应用程序停止并显示以下内容:

RAR5117 : Failed to obtain/create connection from connection pool [ mysql_testPool ]. Reason : In-use connections equal max-pool-size and expired max-wait-time. Cannot allocate more connections. RAR5114 : Error allocating connection : [Error in allocating a connection. Cause: In-use connections equal max-pool-size and expired max-wait-time. Cannot allocate more connections.] java.sql.SQLException: Error in allocating a connection. Cause: In-use connections equal max-pool-size and expired max-wait-time. Cannot allocate more connections.

我正在关闭每种方法中的连接和其他资源。该应用程序在独立连接下运行一切正常。

我做错了什么?如有任何提示或建议,我们将不胜感激。

最佳答案

该异常表示应用程序代码泄漏数据库连接的典型案例。您需要确保获取关闭所有这些(ConnectionStatement ResultSet) 在 try-with-resources 中根据正常的 JDBC 习惯用法,在完全相同的方法 block 中进行 block 。

public void create(Entity entity) throws SQLException {
try (
Connection connection = dataSource.getConnection();
PreparedStatement statement = connection.prepareStatement(SQL_CREATE);
) {
statement.setSomeObject(1, entity.getSomeProperty());
// ...
statement.executeUpdate();
}
}

或者当您不使用 Java 7 时,在 try-finally block 中。在 finally 中关闭它们将保证它们在出现异常时也被关闭。

public void create(Entity entity) throws SQLException {
Connection connection = null;
PreparedStatement statement = null;

try {
connection = dataSource.getConnection();
statement = connection.prepareStatement(SQL_CREATE);
statement.setSomeObject(1, entity.getSomeProperty());
// ...
statement.executeUpdate();
} finally {
if (statement != null) try { statement.close(); } catch (SQLException logOrIgnore) {}
if (connection != null) try { connection.close(); } catch (SQLException logOrIgnore) {}
}
}

是的,您仍然需要自己关闭连接,即使在使用连接池时也是如此。这是初学者的一个常见错误,他们认为它会自动处理关闭。这不正确。连接池即返回一个包装连接,它在 close() 中执行类似以下操作:

public void close() throws SQLException {
if (this.connection is still eligible for reuse) {
do not close this.connection, but just return it to pool for reuse;
} else {
actually invoke this.connection.close();
}
}

不关闭它们会导致连接不会被释放回池中以供重用,因此它将一次又一次地获取一个新连接,直到数据库用完连接,这将导致您的应用程序崩溃。

另见:

关于java - JDBC MySql连接池实践避免连接池耗尽,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2313197/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com