ssh 不能釋放tomcat數據庫連接池中的連接

在Spring+hebernate中 Cannot get a connection, pool error Timeout waiting for idle object異常的解決辦法
   最近寫了個留言板,tomcat+Spring+hibernate+MyEclipse
   使用jdbc連接數據庫所有功能都沒問題,發佈到tomcat中也沒問題,可是如果使用tomcat的數據源,來連接數據庫,開始很正常,但是刷新幾次就會出現這個異常……2008-04-26 22:35:40,812 WARN [org.hibernate.util.JDBCExceptionReporter] - SQL Error: 0, SQLState: null
2008-04-26 22:35:40,812 ERROR [org.hibernate.util.JDBCExceptionReporter] - Cannot get a connection, pool error Timeout waiting for idle object
2008-04-26 22:35:40,812 WARN [org.hibernate.util.JDBCExceptionReporter] - SQL Error: 0, SQLState: null
2008-04-26 22:35:40,812 ERROR [org.hibernate.util.JDBCExceptionReporter] - Cannot get a connection, pool error Timeout waiting for idle object
2008-04-26 22:35:40,812 ERROR [com.dao.MessageDAO] - find all failed
org.springframework.jdbc.UncategorizedSQLException: Hibernate operation: Cannot open connection; uncategorized SQLException for SQL [???]; SQL state [null]; error code [0]; Cannot get a connection, pool error Timeout waiting for idle object; nested exception is org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
Caused by:
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
    at org.apache.tomcat.dbcp.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:104)
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:880)
    at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection (LocalDataSourceConnectionProvider.java:81)
    at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:417)
    at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:144)
    at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:105)
    at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1561)
    at org.hibernate.loader.Loader.doQuery(Loader.java:661)
    at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
    at org.hibernate.loader.Loader.doList(Loader.java:2145)
    at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2029)
    at org.hibernate.loader.Loader.list(Loader.java:2024)
    at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:375)
    at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:308)
    at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:153)
    at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1106)
    at org.hibernate.impl.QueryImpl.list(QueryImpl.java:79)
    at org.springframework.orm.hibernate3.HibernateTemplate$29.doInHibernate(HibernateTemplate.java:849)
    at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:372)
    at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:840)
    at org.springframework.orm.hibernate3.HibernateTemplate.find(HibernateTemplate.java:832)
……………………
開始弄了半天也不知道怎麼回事,後來發現是我自己寫的分頁代碼有問題……原來的代碼如下:
/**
    * 自定義的,用屬性模糊查詢
    *
    * */
    public List find(String propertyName, Object value) {
        log.debug("finding Message instance with property: " + propertyName
              + ", value: " + value);
        try {
           String queryString = "from Message as model where model."
                                   + propertyName + " like "+value+" order by model.time desc";         
        return getHibernateTemplate().find(queryString);
        } catch (RuntimeException re) {
           log.error("find by property name failed", re);
           throw re;
        }
    }


    /**
     *
     * 自定義的方法,獲取指定頁的數據
     *
     * */
    public List gotoPage(int page,int pageSize){

        int totItem = this.findAll().size();//記錄總條數
        int pageNum = totItem / pageSize +1;//總頁數
        int begin = 0;//當前起始記錄數

        begin=page*pageSize-pageSize+1; //計算當前起始位置

        Session s =this.getSession();
        String hql = "from Message message order by message.time desc";
        Query q =s.createQuery(hql);
        q.setFirstResult(begin);
        q.setMaxResults(pageSize);      
        return q.list();
    }
在這句中: Session s =this.getSession();
        String hql = "from Message message order by message.time desc";
        Query q =s.createQuery(hql);
   查詢數據時,Spring並不能夠自動管理連接,也就是說,在使用中這幾句代碼重視不段的獲取數據庫的連接,每調用一次就申請一個連接……直到 tomcat連接池中的連接耗盡……所以就再也申請不到連接了……出現了這個異常,解決辦法是使用事務來管理這段代碼,讓Spring自動管理這段代碼中申請的連接。我使用了Spring AOP自動事務代理……配置文件如下……
<!-- 來自JNDI的tomcat數據源,有連接池。但是用起來怎麼就釋放不了連接呢?程序只知道申請,不知道釋放! -->
    <bean id="JndiDataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName">
            <value>java:comp/env/SqlServer</value>
        </property>
        <property name="resourceRef">
            <value>true</value>
        </property>
    </bean>
    <!-- hibernate的會話工廠 -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource">
            <ref bean="JndiDataSource"></ref>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.SQLServerDialect
                </prop>
                <!-- 顯示SQL,爲了方便測試 -->
                <prop key="hibernate.show_sql">true</prop>
            </props>
        </property>
        <property name="mappingResources">
            <list><!-- 映射文件 -->
                <value>./Message.hbm.xml</value>
                <value>./Setting.hbm.xml</value>
                <value>./Admin.hbm.xml</value>
            </list>
        </property>
    </bean>
    <!-- 事務管理器 -->
    <bean id="transactionManger"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory">
            <ref bean="sessionFactory" />
        </property>
    </bean>
    <!--   配置事務攔截器-->
    <bean id="transactionInterceptor"
        class="org.springframework.transaction.interceptor.TransactionInterceptor">
        <property name="transactionManager">
            <ref bean="transactionManger" />
        </property>
        <!--   下面定義事務傳播屬性-->
        <property name="transactionAttributes">
            <props>
                <prop key="find*">PROPAGATION_REQUIRED</prop>
                <prop key="delete*">PROPAGATION_REQUIRED</prop>
                <prop key="save*">PROPAGATION_REQUIRED</prop>
                <prop key="merge*">PROPAGATION_REQUIRED</prop>
                <prop key="attach*">PROPAGATION_REQUIRED</prop>               
                <prop key="gotoPage">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>
    <!-- 自動代理 -->
    <bean id="autoBeanNameProxyCreator"
        class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
        <property name="beanNames">
            <list>
                <value>*DAO</value>              
                <value>gotoPage</value>
              <value>find</value>
            </list>
        </property>
        <property name="interceptorNames">
            <list>
                <idref local="transactionInterceptor" />
            </list>
        </property>

        <!-- 這裏的配置是必須的,否則無法完成代理的類型轉化
        這是使用CGLIB來生成代理
        -->
        <property name="proxyTargetClass" value="true"/>
    </bean>
    <bean id="MessageDAO" class="com.dao.MessageDAO">
        <property name="sessionFactory">
            <ref bean="sessionFactory"></ref>
        </property>
    </bean>
    <bean id="SettingDAO" class="com.dao.SettingDAO">
        <property name="sessionFactory">
            <ref bean="sessionFactory"></ref>
        </property>
    </bean>
    <bean id="AdminDAO" class="com.dao.AdminDAO">
        <property name="sessionFactory">
            <ref bean="sessionFactory"></ref>
        </property>
    </bean>
</beans>

OK,問題成功解決!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章