Java JDBCMySQL连接池实践,以避免耗尽连接池
我在GlassFish上有一个Java JSF Web应用程序,我想在其中使用连接池。因此,我创建了一个Java JDBCMySQL连接池实践,以避免耗尽连接池,java,mysql,jdbc,glassfish,connection-pooling,Java,Mysql,Jdbc,Glassfish,Connection Pooling,我在GlassFish上有一个Java JSF Web应用程序,我想在其中使用连接池。因此,我创建了一个应用程序作用域bean,它为其他bean提供连接实例: public class DatabaseBean { private DataSource myDataSource; public DatabaseBean() { try { Context ctx = new InitialContext(); e
应用程序
作用域bean,它为其他bean提供连接
实例:
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;
}
}
这样,连接池很快就会被填满;在“db相关”视图中进行几次导航后,应用程序将停止并显示以下内容:
RAR5117:无法从连接池[mysql\u testPool]获取/创建连接。原因:正在使用的连接等于最大池大小和过期的最大等待时间。无法分配更多连接。RAR5114:分配连接时出错:[分配连接时出错。原因:正在使用的连接等于最大池大小和过期的最大等待时间。无法分配更多连接。]java.sql.SQLException:分配连接时出错。原因:正在使用的连接等于最大池大小和过期的最大等待时间。无法分配更多连接
我正在用各种方法关闭连接和其他资源。应用程序在独立连接下运行正常
我做错了什么?任何提示或建议都将不胜感激。此异常表示应用程序代码泄漏数据库连接的典型情况。您需要确保按照正常的JDBC习惯用法,在同一个方法块中的块中获取并关闭它们(
连接,语句和结果集
)
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
块中。最后在中关闭它们将保证在异常情况下也会关闭它们
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()中执行以下操作:
不关闭它们将导致连接无法释放回池中以供重用,因此它将一次又一次地获取新连接,直到数据库耗尽连接,从而导致应用程序崩溃
另见:
如果您需要JDBC连接池,为什么不依赖现有的连接池呢?顺便说一句,JDBC连接池在这些java应用服务器中或多或少被认为是一个标准特性,在我看来,如果您只是对创建应用程序感兴趣,您不应该自己构建它
这里有一个链接可以帮助您开始:
您可能应该做的是了解如何让您的应用程序使用jndi从池中获取连接。他已经在这么做了吗?他已经在appserver中配置了连接池数据源。他只是没有按照例外情况正确关闭资源。感谢您的全面回答,这真的很有帮助!我用app-modifications编辑了我的评论。再次感谢您提供的精彩信息!
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();
}
}