net.sf.hibernate.util.JDBCExceptionReporter - 连接org.postgresql.jdbc3g.Jdbc3gConnection已关闭

时间:2013-04-01 12:39:22

标签: hibernate tomcat6 quartz-scheduler postgresql-9.2

我在我的某个生产环境中遇到此问题。它经常发生,但并不总是在应用程序的相同部分,它是非常随机的。

部署在此环境中的应用程序与部署在不同计算机上的其他应用程序非常相似,使用相同的技术和关闭设置,但错误仅发生在此环境中,因此很难找到问题。

我必须说这些错误最近已经开始出现,因为有几处更新:

应用程序从Windows迁移到Linux

PostgresSQL 8.2到9.2

Tomcat 5到Tomcat 6

所有这些更改也已在其他未完全遇到任何问题的已部署应用程序上完成。

应用程序使用的技术是:

Hibernate 2.1.6

PostgreSQL 9.2

Tomcat 6.0.35

context.xml中的配置是:

<Resource name="jdbc/psa" auth="Container" type="javax.sql.DataSource"
        driverClassName="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/psa?compatible=7.4"
        username="xxx" password="xxx" maxActive="100" maxIdle="30"
        maxWait="10000" factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory"
        defaultAutoCommit="false" removeAbandoned="true"
        removeAbandonedTimeout="60" logAbandoned="true" validationQuery="select 1"
        testOnBorrow="true" testOnReturn="true" testWhileIdle="true"
        timeBetweenEvictionRunsMillis="300000"/>

请注意,驱逐只是试图解决问题,但没有结果。

接下来是典型问题的流程:

1.-打开一个新的Hibernate会话

2.-我在查询之前检查此会话是否已打开并已连接

3.-在日志上看到会话打开有效后,会产生异常

- ADDED

其中一个错误的完整堆栈跟踪如下:

29 03 2013 10:00:00 INFO EasyApScheduler_Worker-8 com.psa.accounting.eureca.logic.EurecaNLAccountingLogic - -- Process EURECA_NL starts
    29 03 2013 10:00:00 INFO EasyApScheduler_Worker-2 com.psa.accounting.eureca.logic.EurecaSCAccountingLogic - -- Process EURECA_SC starts
    29 03 2013 10:00:00 DEBUG EasyApScheduler_Worker-2 com.xeridia.persistence.ServiceLocator - Session opened: net.sf.hibernate.impl.SessionImpl@22880d66. Opened: true, Connected: true
    29 03 2013 10:00:00 DEBUG EasyApScheduler_Worker-2 com.xeridia.persistence.ServiceLocator - [getConnection]|16|Thread[EasyApScheduler_Worker-2,4,main]|
    29 03 2013 10:00:00 DEBUG EasyApScheduler_Worker-2 com.xeridia.persistence.ServiceLocator - [getConnection]|16|Thread[EasyApScheduler_Worker-2,4,main]|com.easyap.invoice.persistence.InvoiceDAOHibernate.<init>(InvoiceDAOHibernate.java:364)
    29 03 2013 10:00:00 ERROR EasyApScheduler_Worker-8 net.sf.hibernate.util.JDBCExceptionReporter - Connection org.postgresql.jdbc3g.Jdbc3gConnection@1b0ca3f7 is closed.
    29 03 2013 10:00:00 DEBUG EasyApScheduler_Worker-2 com.xeridia.persistence.ServiceLocator - [getConnection]|16|Thread[EasyApScheduler_Worker-2,4,main]|com.psa.invoice.persistence.PSAInvoiceDAOHibernate.<init>(PSAInvoiceDAOHibernate.java:52)
    29 03 2013 10:00:00 ERROR EasyApScheduler_Worker-8 net.sf.hibernate.util.JDBCExceptionReporter - Connection org.postgresql.jdbc3g.Jdbc3gConnection@1b0ca3f7 is closed.
    29 03 2013 10:00:00 ERROR EasyApScheduler_Worker-8 net.sf.hibernate.util.JDBCExceptionReporter - Could not execute query
    java.sql.SQLException: Connection org.postgresql.jdbc3g.Jdbc3gConnection@1b0ca3f7 is closed.
        at org.apache.tomcat.dbcp.dbcp.DelegatingConnection.checkOpen(DelegatingConnection.java:398)
        at org.apache.tomcat.dbcp.dbcp.DelegatingConnection.prepareStatement(DelegatingConnection.java:279)
        at org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(PoolingDataSource.java:313)
        at net.sf.hibernate.impl.BatcherImpl.getPreparedStatement(BatcherImpl.java:257)
        at net.sf.hibernate.impl.BatcherImpl.getPreparedStatement(BatcherImpl.java:232)
        at net.sf.hibernate.impl.BatcherImpl.prepareQueryStatement(BatcherImpl.java:65)
        at net.sf.hibernate.loader.Loader.prepareQueryStatement(Loader.java:779)
        at net.sf.hibernate.loader.Loader.doQuery(Loader.java:265)
        at net.sf.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:133)
        at net.sf.hibernate.loader.Loader.doList(Loader.java:1033)
        at net.sf.hibernate.loader.Loader.list(Loader.java:1024)
        at net.sf.hibernate.hql.QueryTranslator.list(QueryTranslator.java:854)
        at net.sf.hibernate.impl.SessionImpl.find(SessionImpl.java:1544)
        at net.sf.hibernate.impl.QueryImpl.list(QueryImpl.java:39)
        at com.xeridia.persistence.BaseDAOHibernate.findByQuery(BaseDAOHibernate.java:312)
        at com.xeridia.persistence.BaseDAOHibernate.findByQuery(BaseDAOHibernate.java:291)
        at com.psa.invoice.persistence.PSAInvoiceDAOHibernate.getAccountingInvoicesWithNoProblem(PSAInvoiceDAOHibernate.java:215)
        at com.psa.accounting.eureca.logic.EurecaNLAccountingLogic.getAccountingDataFromDB(EurecaNLAccountingLogic.java:469)
        at com.psa.accounting.eureca.logic.EurecaNLAccountingLogic.process(EurecaNLAccountingLogic.java:207)
        at com.psa.accounting.eureca.scheduler.CronEurecaNLAccounting.execute(CronEurecaNLAccounting.java:91)
        at org.quartz.core.JobRunShell.run(JobRunShell.java:203)
        at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520)

管理所有Hibernate会话的类是一个名为ServiceLocator的类。此类的getConnection()方法返回一个新连接,其代码如下:

synchronized (session) {
                s = (Session) session.get();
                if ((s == null)||(!s.isOpen())) {
                    s = null;
                    s = getSessionFactory().openSession();
                    if (s != null) {
                        log.debug("Session opened: " + s + ". Opened: " + s.isOpen() +
                                ", Connected: " + s.isConnected());
                        printThreadDataForClosedConnections("[getConnection]");
                    }
                    session.set(s);
                }
                if (!s.isConnected()) {
                    s.reconnect();
                    log.debug("Session reconnected: " + s + ". Opened: " + s.isOpen() +
                            ", Connected: " + s.isConnected());
                    printThreadDataForClosedConnections("[getConnection]");
                }
            }

对象'session'声明为:

public static final ThreadLocal session = new ThreadLocal();

为不同的线程获取不同的会话,因此在线程之间关闭会话时应该不存在问题。

您在上面的堆栈跟踪中可以看到EasyApScheduler_Worker-2因if ((s == null)||(!s.isOpen())) {而获取新连接但EasyApScheduler_Worker-8没有,这意味着它的'会话'对象存在且已打开或无法获取连接和对应于错误29 03 2013 10:00:00 ERROR EasyApScheduler_Worker-8 net.sf.hibernate.util.JDBCExceptionReporter - Connection org.postgresql.jdbc3g.Jdbc3gConnection@1b0ca3f7 is closed.

的第一个跟踪

我不知道问题是来自Hibernate,Postgres还是Tomcat。我几乎没有在谷歌上发现这个错误,所以我希望你能帮我一臂之力。

请询问您需要的任何额外信息或设置,以便提供帮助。

提前致谢。

1 个答案:

答案 0 :(得分:0)

我已经修好了。

Quartz线程存在问题。默认情况下,Quartz管理一个线程池,这些线程在不同作业的执行之间重复使用。我的类ServiceLocator负责打开和关闭连接,它基于ThreadLocal对象。似乎我的一个调度作业没有正确关闭它的连接,之后,在与此相同的线程上执行的所有作业都会导致错误。

我无法弄清楚什么是有问题的工作,我最后做的是更改Quartz的默认连接池以获得自定义的连接池,这样我就为每个作业执行创建一个新线程,而不是为所有工作共享一定数量的线程。

这是我编写的Quartz自定义线程池,以防它对某人有用:

public class SimpleNoThreadPooling implements ThreadPool {

    public int getPoolSize() {
        return 0;
    }


    public Log getLog() {
        return LogFactory.getLog(SimpleNoThreadPooling.class);
    }

    public void initialize() throws SchedulerConfigException { }

    class WorkerThread extends Thread {

        private Runnable runnable = null;

        /**
         * <p>
         * Create a worker thread, start it, execute the runnable and terminate
         * the thread (one time execution).
         * </p>
         */
        WorkerThread(Runnable runnable) {
            this.runnable = runnable;
            start();
        }

        public void run() {
            if (runnable != null) {
                try {
                    runnable.run();
                } catch (Exception exceptionInRunnable) {
                    try {
                        getLog().error("Error while executing the Runnable: ",
                            exceptionInRunnable);
                    } catch(Exception e) {  
                        // ignore to help with a tomcat glitch
                    }
                }
            }
        }
    }

    public boolean runInThread(Runnable runnable) {
        new WorkerThread(runnable);
        return true;
    }

    public void shutdown(boolean waitForJobsToComplete) { }

}