代码之家  ›  专栏  ›  技术社区  ›  BuddyJoe

基础知识-解决Hibernate/JDBC连接池问题

  •  15
  • BuddyJoe  · 技术社区  · 14 年前

    Hibernate从底层连接池获得的数据库连接的责任是什么。它是否在使用连接之前测试连接是否已关闭?如果是的话,从游泳池里再找一个连接?

    从Catalina日志:

    04-Nov-2010 21:54:52.691 WARNING org.apache.tomcat.jdbc.pool.ConnectionPool.abandon Connection has been abandoned PooledConnection[ConnectionID:8]:java.lang.Exception
        at org.apache.tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.java:926)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:681)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:545)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:166)
        at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:106)
    

    2010-11-04 21:54:52,705 [tomcat-http--18] WARN  util.JDBCExceptionReporter  - SQL Error: 0, SQLState: 08S01
    2010-11-04 21:54:52,707 [tomcat-http--18] ERROR util.JDBCExceptionReporter  - Socket closed
    2010-11-04 21:54:52,708 [tomcat-http--18] ERROR transaction.JDBCTransaction  - JDBC rollback failed
    java.sql.SQLException: Connection has already been closed.
        at org.apache.tomcat.jdbc.pool.ProxyConnection.invoke(ProxyConnection.java:112)
        at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:94)
        at org.apache.tomcat.jdbc.pool.interceptor.AbstractCreateStatementInterceptor.invoke(AbstractCreateStatementInterceptor.java:71)
        at org.apache.tomcat.jdbc.pool.JdbcInterceptor.invoke(JdbcInterceptor.java:94)
        at org.apache.tomcat.jdbc.pool.interceptor.ConnectionState.invoke(ConnectionState.java:132)
        at $Proxy38.rollback(Unknown Source)
        at org.hibernate.transaction.JDBCTransaction.rollbackAndResetAutoCommit(JDBCTransaction.java:217)
        at org.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:196)
        at org.springframework.orm.hibernate3.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:676)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:845)
        at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:822)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.completeTransactionAfterThrowing(TransactionAspectSupport.java:412)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:111)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)
    

    配置 :

    <Resource defaultAutoCommit="false" defaultReadOnly="false"
            defaultTransactionIsolation="SERIALIZABLE"
            driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
            factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
            fairQueue="false" initialSize="10"
            jdbcInterceptors="ConnectionState;StatementFinalizer"
            jmxEnabled="true" logAbandoned="true" maxActive="100"
            maxIdle="10" maxWait="30000"
            minEvictableIdleTimeMillis="10000" minIdle="10"
            name="com.ourcompany.ap.shoppingcart/datasource"
            password="somePassword" removeAbandoned="true"
            removeAbandonedTimeout="60" testOnBorrow="true"
            testOnReturn="false" testWhileIdle="false"
            timeBetweenEvictionRunsMillis="5000"
            type="javax.sql.DataSource"
            url="jdbc:sqlserver://approd\approd;databaseName=prod"
            useEquals="false" username="AccessPointNet"
            validationInterval="30000" validationQuery="SELECT 1"/>`
    
    6 回复  |  直到 14 年前
        1
  •  14
  •   Pascal Thivent    14 年前

    Hibernate从底层连接池获得的数据库连接的责任是什么。

    Session 关闭。

    不,Hibernate没有,如果您愿意,检查连接的有效性是连接池的责任。

    我已经包括错误和确认信息如下。任何我可以开始解决这个问题的想法都会很有帮助。

    Caused by: 说什么?关于跟踪:

    2010-11-04 21:54:52,705 [tomcat-http--18] WARN util.JDBCExceptionReporter - SQL Error: 0, SQLState: 08S01 
    2010-11-04 21:54:52,707 [tomcat-http--18] ERROR util.JDBCExceptionReporter - Socket closed
    2010-11-04 21:54:52,708 [tomcat-http--18] ERROR transaction.JDBCTransaction - JDBC rollback failed java.sql.SQLException: Connection has already been closed.
    

    你能以一种确定的方式再现它吗?有网络问题吗?

    以及有关我们正在使用的SQL Server驱动程序设置的任何建议。

    资源

        2
  •  17
  •   Cid    12 年前

    删除bandonedtimeout 值设置为更高的数字。我们面临的问题是由于查询花费了比上述超时更长的时间。

        4
  •  2
  •   mjj1409    11 年前

    我正在使用 liquibase(v1.9) 在我的项目中,当变更集运行在一个空白模式下时,总是需要超过60秒的时间,这导致线程被标记为已放弃,我对增加 removeAbandonedTimeout

        5
  •  1
  •   Jeremy    14 年前

    我在过去处理过一个问题,我们没有正确地将连接返回到池。因此,当使用连接但未返回时,在超时时进行数据库调用将引发异常。

    我们可以通过调用数据库来重现这个问题,等待8小时(postgres的默认超时),然后再次尝试调用数据库。它每次都抛出相同的异常。我们的解决方案是重新思考(或者更好的是, )连接管理策略。

    所以,总而言之,您是否真的通过关闭会话将连接返回到池?

        6
  •  0
  •   erhun    10 年前

    我找到了解决上述异常的方法。

    请看下面的代码:

    public class HibernateUtil {
        private static final SessionFactory sessionFactory = buildSessionFactory();
    
        private static SessionFactory buildSessionFactory() {
            try {
                // Create the SessionFactory from hibernate.cfg.xml
                return new Configuration().configure("hibernate.cfg.xml").buildSessionFactory();
            }
            catch (Throwable ex) {
                ex.printStackTrace();
                // Make sure you log the exception, as it might be swallowed
                System.err.println("Initial SessionFactory creation failed." + ex);
                throw new ExceptionInInitializerError(ex);
            }
        }
    
        public static SessionFactory getSessionfactory() {
            return sessionFactory;
        }
    
        public static Session getSession() {
            Session session=sessionFactory.openSession();
            session.getTransaction().begin();
            return session;
        }
        public static void closeSession(Session session) {
            if(session!=null )
            {
                if(session.getTransaction().isActive())
                {
                    session.getTransaction().commit();
                }
                    session.close();
                    getSessionfactory().close();
            }
        }
    }
    

    只需调用方法 HibernateUtil.closeSession() . 这将解决问题。