我们有一个使用 JPA (Hibernate) 在 Glassfish 上使用 MySQL 的应用程序,它运行良好。
然后我们切换到 PostgreSQL,几乎一切正常。我们唯一的问题是,应用程序在一段时间后停止响应并抛出异常,因为与数据库的连接已关闭:
[#|2012-06-19T21:51:22.050+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=38;_ThreadName=Thread-2;|4816089 [p: thread-pool-1; w: 21] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: 08006
[#|2012-06-19T21:51:22.050+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=38;_ThreadName=Thread-2;|4816089 [p: thread-pool-1; w: 21] ERROR org.hibernate.util.JDBCExceptionReporter - An I/O error occured while sending to the backend.
[#|2012-06-19T21:51:22.052+0200|SEVERE|glassfish3.1.2|javax.enterprise.resource.resourceadapter.com.sun.enterprise.resource|_ThreadID=38;_ThreadName=Thread-2;|RAR5031:System Exception
javax.resource.spi.LocalTransactionException: This connection has been closed.
at com.sun.gjc.spi.LocalTransactionImpl.rollback(LocalTransactionImpl.java:134)
at com.sun.enterprise.resource.ConnectorXAResource.rollback(ConnectorXAResource.java:213)
at com.sun.enterprise.transaction.JavaEETransactionImpl.rollback(JavaEETransactionImpl.java:571)
at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.rollback(JavaEETransactionManagerSimplified.java:893)
at com.sun.enterprise.transaction.UserTransactionImpl.rollback(UserTransactionImpl.java:234)
at ch.ethz.id.wai.lakshmi.engine.common.TransactionHelper.rollbackTransaction(TransactionHelper.java:43)
at ch.ethz.id.wai.lakshmi.stdcmp.tracking.StandardTracking.updateStatus(StandardTracking.java:50)
at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.updateTrackingStatus(LakshmiServerBean.java:992)
at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.executeNextWorkflowStep(LakshmiServerBean.java:771)
at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.executeNextWorkflowStep(LakshmiServerBean.java:683)
at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.continueWorkflow(LakshmiServerBean.java:602)
at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.processSubmitOrderRequest(LakshmiServerBean.java:487)
at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.onMessage(LakshmiServerBean.java:360)
at sun.reflect.GeneratedMethodAccessor133.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:4180)
at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5368)
at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5348)
at com.sun.ejb.containers.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:1099)
at com.sun.ejb.containers.MessageBeanListenerImpl.deliverMessage(MessageBeanListenerImpl.java:81)
at com.sun.enterprise.connectors.inbound.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:171)
at $Proxy264.onMessage(Unknown Source)
at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:260)
at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:114)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)
Caused by: org.postgresql.util.PSQLException: This connection has been closed.
at org.postgresql.jdbc2.AbstractJdbc2Connection.checkClosed(AbstractJdbc2Connection.java:714)
at org.postgresql.jdbc2.AbstractJdbc2Connection.rollback(AbstractJdbc2Connection.java:731)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection$ConnectionHandler.invoke(AbstractJdbc23PooledConnection.java:352)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection$ConnectionHandler.invoke(AbstractJdbc23PooledConnection.java:352)
at $Proxy161.rollback(Unknown Source)
at com.sun.gjc.spi.LocalTransactionImpl.rollback(LocalTransactionImpl.java:128)
... 28 more
我们以同样的方式为 MySQL 和 PostgreSQL 创建连接池:
asadmin create-jdbc-connection-pool \
--restype javax.sql.DataSource \
--datasourceclassname org.postgresql.jdbc2.optional.PoolingDataSource \
--property URL='jdbc:postgresql://127.0.0.1:5432/doi':serverName=localhost:databaseName=doi:user=doi:password=******** doi
和
asadmin create-jdbc-connection-pool \
--restype javax.sql.DataSource \
--datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource \
--property serverName=127.0.0.1:dataBaseName=doi:user=doi:********=doi:schema=doi doi
如何配置数据池以关闭空闲连接或使其保持活动状态并避免关闭连接错误?