基础知识 – Hibernate / JDBC连接池问题疑难解答

什么是Hibernate对从底层连接池获取的数据库连接的责任。 是否在使用之前测试连接是否已关闭? 如果是这样从游泳池获得另一个连接?

我在下面列出了错误和确认信息。 任何我可以开始解决这个问题的想法都会非常有帮助。 以及我们正在使用的SQL Server驱动程序设置的任何建议。

从Catalina日志:

 04-Nov-2010 21:54:52.691警告org.apache.tomcat.jdbc.pool.ConnectionPool.abandon连接已被放弃PooledConnection [ConnectionID:8]:java.lang.Exception
    在org.apache.tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.java:926)
    在org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:681)
    在org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:545)
    在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错误:0,SQLState:08S01
 2010-11-04 21:54:52,707 [tomcat-http  -  18] ERROR util.JDBCExceptionReporter  - 套接字已关闭
 2010-11-04 21:54:52,708 [tomcat-http  -  18] ERROR transaction.JDBCTransaction  -  JDBC回滚失败
 java.sql.SQLException:连接已关闭。
    在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)
    在$ Proxy38.rollback(未知来源)
    在org.hibernate.transaction.JDBCTransaction.rollbackAndResetAutoCommit(JDBCTransaction.java:217)
    在org.hibernate.transaction.JDBCTransaction.rollback(JDBCTransaction.java:196)
    在org.springframework.orm.hibernate3.HibernateTransactionManager.doRollback(HibernateTransactionManager.java:676)
    在org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:845)
    在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)
    在org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    在org.springframework.aop.framework.Cglib2AopProxy $ DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)

配置

` 

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

并不多,在Session关闭时释放它。

是否在使用之前测试连接是否已关闭? 如果是这样从游泳池获得另一个连接?

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

我在下面列出了错误和确认信息。 任何我可以开始解决这个问题的想法都会非常有帮助。

你到底在做什么样的过程? 长期交易? 它超时了吗? Caused by:什么Caused by:说什么? 关于追踪:

 2010-11-04 21:54:52,705 [tomcat-http  -  18] WARN util.JDBCExceptionReporter  -  SQL错误:0,SQLState:08S01 
 2010-11-04 21:54:52,707 [tomcat-http  -  18] ERROR util.JDBCExceptionReporter  - 套接字已关闭
 2010-11-04 21:54:52,708 [tomcat-http  -  18] ERROR transaction.JDBCTransaction  -  JDBC回滚失败java.sql.SQLException:Connection已经关闭。

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

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

我在下面添加了一个关于Tomcat和连接池配置的很好的资源。 但不是特定于SQL Server。

资源

  • 配置jdbc-pool以实现高并发性

我有一个类似的问题,通过将removeAbandonedTimeout值增加到更高的数字来解决。 我们遇到的问题是由于查询花费了较长时间,上述超时。

我们通常使用dbcp解决这个问题,并在定义数据源时提供validationQuery。 然后,dbcp将通过发出该查询来validation池连接的可用性(并在将它们返回到应用程序之前透明地重新创建连接,如果它不再有效)。

查看http://tomcat.apache.org/tomcat-6.0-doc/jndi-datasource-examples-howto.html了解更多详情。

我目前在我的项目中使用liquibase(v1.9) ,并且当liquibase(v1.9)针对空白模式运行时,它总是花费超过60秒,这导致线程被标记为放弃我不会因增加removeAbandonedTimeout值而兴奋,但是这是我能找到的唯一能够防止这个问题的解决方案; 但是,在初始模式填充完成后,这很少出现问题,因此我将值设置回60秒。

我曾经处理过一个问题,我们没有正确地将连接返回池中。 因此,当使用连接而不返回连接时,在超时时进行数据库调用会引发exception。

我们能够通过调用数据库来重现该问题,等待8小时(postgres的默认超时)并尝试再次调用数据库。 它每次抛出相同的exception。 我们的解决方案是重新思考(或更好地, 添加 )连接管理策略。

总而言之,您是否通过关闭会话实际返回到池的连接?

我得到了上述exception的解决方案。 关闭会话时,只需关闭会话工厂的实例。

看下面的代码:

 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() 。 这将解决问题。