Java 为什么我们的连接池要关闭?
我们有一个JSF2.0 Web服务器,运行在ApacheTomcat7.0.54上,运行在WindowsServer2008R2上。我们有两台SQL Server在运行它的机器上,另一台托管我们的库存软件。我们网页的一部分是验证添加的零件号。在阅读了连接池是与SQL Server对话的最佳实践之后,我们创建了一个连接池,并将其用于针对清单软件的一些验证 因为我想要一种能够检查连接池运行状况的方法,所以我创建了一个测试页面,其中包含一个ViewScope支持bean,该bean验证了2个已知的良好部件号。今天是本周第二次出现错误消息“连接已关闭”。由于我是conenction pools的新手,似乎找不到任何有关这方面的信息,我对我们没有正确设置的内容感到困惑。我刚刚重置了Apache服务器,它已备份并运行。所以为了创建连接池,我在应用程序的META-INF/context.xml中添加了一些代码Java 为什么我们的连接池要关闭?,java,sql-server,jsf,tomcat,connection-pooling,Java,Sql Server,Jsf,Tomcat,Connection Pooling,我们有一个JSF2.0 Web服务器,运行在ApacheTomcat7.0.54上,运行在WindowsServer2008R2上。我们有两台SQL Server在运行它的机器上,另一台托管我们的库存软件。我们网页的一部分是验证添加的零件号。在阅读了连接池是与SQL Server对话的最佳实践之后,我们创建了一个连接池,并将其用于针对清单软件的一些验证 因为我想要一种能够检查连接池运行状况的方法,所以我创建了一个测试页面,其中包含一个ViewScope支持bean,该bean验证了2个已知的良好
<Resource type="javax.sql.DataSource"
name="jdbc/FOODB"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://Foobar\Inventory;databaseName=FooInventory;user=johnDoe;password=astrongpassword;"
/>
我必须使用ConnectionPool的基本概念是,我有一个名为SqlAccessCommand的接口。它或多或少是一种适配器模式。在我的测试页面中,我使用runsafe方法,以便显示错误消息。这里是RunUnsafe方法
protected static DataSource getDataSource() throws NamingException {
Context context = (Context) new InitialContext().lookup("java:/comp/env");
DataSource ds = (DataSource) context.lookup("jdbc/FOODB");
return ds;
}
public static <T> T RunUnsafe(SqlAccessCommand<T> command) throws NamingException, SQLException {
try {
DataSource ds = getDataSource();
try (Connection connection = ds.getConnection();
PreparedStatement statement = connection.prepareStatement(command.getSqlStatement())) {
command.prepareStatment(statement);
try (ResultSet rs = statement.executeQuery()) {
return command.getResults(rs);
}
}
} catch (NamingException | SQLException e) {
Logger.getLogger(AOSqlInformationHolder.class.getName()).log(Level.SEVERE, null, e);
throw e;
}
}
受保护的静态数据源getDataSource()引发NamingException{
Context Context=(Context)new InitialContext().lookup(“java:/comp/env”);
DataSource ds=(DataSource)context.lookup(“jdbc/FOODB”);
返回ds;
}
公共静态运行不安全(SqlAccessCommand命令)引发NamingException,SQLException{
试一试{
DataSource ds=getDataSource();
try(Connection=ds.getConnection();
PreparedStatement=connection.prepareStatement(command.getSqlStatement()){
命令.准备声明(声明);
try(ResultSet rs=statement.executeQuery()){
return命令.getResults(rs);
}
}
}捕获(NamingException | SQLException e){
Logger.getLogger(AOSqlInformationHolder.class.getName()).log(Level.SEVERE,null,e);
投掷e;
}
}
正如您所看到的,我使用了try with resources,无论发生什么情况,它都应该在使用后关闭我的连接。就像try/catch/finally一样,只是更干净(IMO)。因此,当我的连接打开时,这一切正常。到目前为止,我必须重新启动服务器(因为我不知道如何以任何其他方式重新打开所述连接),我缺少什么?如果需要更多的谜题,请给我留言,我会尽我所能发布。多谢各位
编辑
只是查看了日志文件,今天早上抛出了这个异常
com.microsoft.sqlserver.jdbc.SQLServerException:对等方重置连接:套接字写入错误
根据到目前为止的评论,它被假定为超时。此错误消息是否仍指向该方向?根据com.microsoft.sqlserver.jdbc.SQLServerException:Connection reset by peer:socket write error的日志消息,您的连接几乎肯定会由于不活动而超时,您可以阅读以下说明: 连接被对等方强制关闭。这通常是由于超时或重新启动导致远程套接字上的连接丢失造成的
您需要在连接池配置中添加一些选项1,以检测连接是否仍然有效 最简单的方法是运行一个简单的SQL语句2来测试连接 因此,池配置可以是:
注释
我建议使用放弃配置选项
<Resource type="javax.sql.DataSource"
name="jdbc/FOODB"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
url="jdbc:sqlserver://Foobar\Inventory;databaseName=FooInventory;user=johnDoe;password=astrongpassword;"
removeAbandoned="true"
removeAbandonedTimeout="60"
logAbandoned="true"
/>
连接可能在不活动后超时。@ElliottFrisch这不是只有在我不关闭连接的情况下才会发生吗?如果是这样的话,那不是try with resources的作用吗?当您使用池时,连接不会关闭;他们回到游泳池。最后(如果连接未使用的时间足够长),数据库会假定连接已损坏并将其关闭。您需要查看池配置选项以获得解决方案。@ElliottFrisch请参阅编辑谢谢您找到此选项列表。我打算使用同一文档中的废弃删除内容,但这似乎更符合逻辑。修改,因为这个答案实际上有一个解决方案。我认为应该注意的是,这个解决方案会导致在每个查询上验证连接的成本。遗憾的是,没有什么灵丹妙药。使用这种解决方案,执行语句只是为了从池中获得连接。e、 g.Connection conn=datasource.getConnection()代码>。也许您想查看我的答案中提供的链接上的选项。removeAbandoned
在应用程序未正确关闭连接时非常有用。但是,OP的问题是连接被数据库关闭。