簡體   English   中英

基礎知識 - Hibernate / JDBC連接池問題疑難解答

[英]Basics - Troubleshooting Hibernate / JDBC Connection Pool Issue

什么是Hibernate對從底層連接池獲取的數據庫連接的責任。 是否在使用之前測試連接是否已關閉? 如果是這樣從游泳池獲得另一個連接?

我在下面列出了錯誤和確認信息。 任何我可以開始解決這個問題的想法都會非常有幫助。 以及我們正在使用的SQL Server驅動程序設置的任何建議。

從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"/>`

我有一個類似的問題,通過將removeAbandonedTimeout值增加到更高的數字來解決。 我們遇到的問題是由於查詢花費了更長的時間,上面提到的超時。

什么是Hibernate對從底層連接池獲取的數據庫連接的責任。

並不多,在Session關閉時釋放它。

是否在使用之前測試連接是否已關閉? 如果是這樣從游泳池獲得另一個連接?

不,Hibernate沒有,如果你願意,檢查連接的有效性是連接池的責任。

我在下面列出了錯誤和確認信息。 任何我可以開始解決這個問題的想法都會非常有幫助。

你到底在做什么樣的過程? 長期交易? 它超時了嗎? Caused by:什么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驅動程序設置的任何建議。

我在下面添加了一個關於Tomcat和連接池配置的優秀資源。 但不是特定於SQL Server。

資源

我目前在我的項目中使用liquibase(v1.9) ,並且當liquibase(v1.9)針對空白模式運行時,它總是花費超過60秒,這導致線程被標記為放棄我不會因增加removeAbandonedTimeout值而興奮,但是這是我能找到的唯一能夠防止這個問題的解決方案; 但是,在初始模式填充完成后,這很少出現問題所以我將值設置回60秒。

我們通常使用dbcp解決這個問題,並在定義數據源時提供validationQuery。 然后,dbcp將通過發出該查詢來驗證池連接的可用性(並且在將它們返回到應用程序之前透明地重新創建連接,如果它不再有效)。

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

我曾經處理過一個問題,我們沒有正確地將連接返回池中。 因此,當使用連接而不返回連接時,在超時時進行數據庫調用會引發異常。

我們能夠通過調用數據庫來重現該問題,等待8小時(postgres的默認超時)並嘗試再次調用數據庫。 它每次拋出相同的異常。 我們的解決方案是重新思考(或更好地, 添加 )連接管理策略。

總而言之,您是否通過關閉會話實際返回到池的連接?

我得到了上述異常的解決方案。 關閉會話時,也可以關閉會話工廠的實例。

看下面的代碼:

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() 這將解決問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM