我们已经部署了几个在同一个 tomcat 容器中运行的应用程序,并通过 JNDI 查找连接到我们的 postgresql 数据库。这是经过清理的配置 (server.xml
):
<Resource name="MyDataSource"
auth="Container"
type="javax.sql.DataSource"
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://myrdsinstance.com:5432/MyDatabase"
username="my_username"
password="my_password" />
这几个月都运行良好,但今天早上任何读取数据库的尝试都失败了:
org.postgresql.util.PSQLException: This connection has been closed.
org.postgresql.jdbc2.AbstractJdbc2Connection.checkClosed(AbstractJdbc2Connection.java:843)
org.postgresql.jdbc2.AbstractJdbc2Connection.getAutoCommit(AbstractJdbc2Connection.java:804)
sun.reflect.GeneratedMethodAccessor1079.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:606)
org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:126)
org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:109)
org.apache.tomcat.jdbc.pool.DisposableConnectionFacade.invoke(DisposableConnectionFacade.java:80)
com.sun.proxy.$Proxy30.getAutoCommit(Unknown Source)
org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:68)
org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:160)
org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1309)
org.hibernate.ejb.TransactionImpl.begin(TransactionImpl.java:57)
org.springframework.orm.jpa.DefaultJpaDialect.beginTransaction(DefaultJpaDialect.java:70)
org.springframework.orm.jpa.vendor.HibernateJpaDialect.beginTransaction(HibernateJpaDialect.java:59)
org.springframework.orm.jpa.JpaTransactionManager.doBegin(JpaTransactionManager.java:377)
org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
临时修复是重新启动 tomcat7
服务,我假设它重新打开了关闭的数据库连接。但现在我正在调查根本原因,希望能找到一个长期的解决办法。我从 catalina.out
中找到:
2015-02-09 14:15:55,260 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] - SQL Error: 0, SQLState: 08003
来自 the PostgreSQL error codes doc我看到这意味着 connection_does_not_exist
。
我已经进行了一些谷歌搜索,但找不到与这个确切问题相关的太多信息。我认为如果连接关闭,它将由 JDBC、Hibernate 甚至 GORM(对于 grails 应用程序)处理。我在这里遗漏了什么明显的东西吗?
最佳答案
检查 commons-dbcp
中 BasicDataSource
的代码,我得出的结论是,通过将 validationQuery
指定为我们允许容器在连接到达我们的代码之前验证连接是否有效的数据源。当然在tomcat验证到我们的代码之间连接失效的可能性还是很小的,所以这个方案并不理想。简而言之:
<Resource name="MyDataSource"
auth="Container"
type="javax.sql.DataSource"
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://myrdsinstance.com:5432/MyDatabase"
username="my_username"
password="my_password"
validationQuery="SELECT 1" />
希望有比这更好的解决方案,但我想我会发布我们为其他任何 google 员工所做的事情。
关于java - Tomcat JNDI PSQLException : This connection has been closed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28413982/