JDBC MySql连接池的做法可以避免耗尽连接池

我在GlassFish上有一个Java-JSF Web应用程序,我想在其中使用连接池。 因此,我创build了一个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; } } 

通过这种方式,连接池可以非常快地填充; 在通过“db-related”视图进行了几次导航之后,应用程序将停止并显示以下内容:

RAR5117:无法从连接池[mysql_testPool]获取/创build连接。 原因:正在使用的连接等于最大池大小和最大等待时间。 无法分配更多的连接。 RAR5114:分配连接时出错:[分配连接时出错。 原因:正在使用的连接等于最大池大小和最大等待时间。 无法分配更多连接。] java.sql.SQLException:分配连接时出错。 原因:正在使用的连接等于最大池大小和最大等待时间。 无法分配更多的连接。

我正在closures每个方法中的连接和其他资源。 应用程序在独立连接中运行正常。

我究竟做错了什么? 任何提示或build议,将不胜感激。

exception表示泄露数据库连接的典型应用程序代码。 您需要确保您按照正常的JDBC惯用法在同一个方法块中的try-with-resources块中获取closures它们( ConnectionStatement ResultSet )。

 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块中。 finallyclosures它们将保证在例外的情况下也closures它们。

 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) {} } } 

是的,即使使用连接池,您仍然需要自己closures连接。 首先,他们认为自动处理closures是一个普遍的错误。 这是不正确的 。 连接池即返回一个封装的连接,在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(); } } 

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

也可以看看:

  • Connection,Statement和ResultSet在JDBC中多久closures一次?
  • 在multithreading系统中使用静态java.sql.Connection实例是否安全?
  • 在池中closuresJDBC连接

如果你需要JDBC连接池,为什么不依赖于已有的东西? AFAIK,JDBC连接池在这些Java应用程序服务器和IMO中被认为是标准function,如果您只是想创build一个应用程序,您不应该自行构build它。

这里有一个链接,应该让你开始: http : //weblogs.java.net/blog/2007/09/12/totd-9-using-jdbc-connection-pooljndi-name-glassfish-rails-application

你应该做的是找出如何让你的应用程序使用jndi从池中获取连接。