2014-05-06 170 views
4

我一直在努力解決這個問題一段時間了。我有一個基於Web的應用程序,使用Struts2,spring和Hibernate。我使用Spring將struts動作和業務和dao層連接在一起。 我正在使用JMeter來加載測試應用程序。當我模擬1個用戶重複發送獲取請求時,該應用程序運行良好,沒有問題。但是,當我添加一些更多的用戶的,有一段時間我碰到下面的錯誤後:org.hibernate.exception.GenericJDBCException:無法打開連接

Caused by: org.hibernate.exception.GenericJDBCException: Cannot open connection 
    at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:140) 
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:128) 
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) 
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52) 
    at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449) 
    at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167) 
    at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:160) 
    at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:81) 
    at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1473) 
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:510) 
    ... 104 more 
Caused by: java.sql.SQLException: Listener refused the connection with the following error: 
ORA-12519, TNS:no appropriate service handler found 
The Connection descriptor used by the client was: 
192.168.1.118:1521:BAADB 

    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) 
    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:261) 
    at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:387) 
    at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:414) 
    at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:165) 
    at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:35) 
    at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:801) 
    at java.sql.DriverManager.getConnection(DriverManager.java:582) 
    at java.sql.DriverManager.getConnection(DriverManager.java:154) 
    at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriverManager(DriverManagerDataSource.java:173) 
    at org.springframework.jdbc.datasource.DriverManagerDataSource.getConnectionFromDriver(DriverManagerDataSource.java:164) 
    at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnectionFromDriver(AbstractDriverBasedDataSource.java:149) 
    at org.springframework.jdbc.datasource.AbstractDriverBasedDataSource.getConnection(AbstractDriverBasedDataSource.java:119) 
    at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81) 
    at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446) 
    ... 109 more 

所以,我認爲它是一個連接泄漏,但不應該我得到同樣的錯誤,當我模擬一個用戶不斷髮送請求(唯一的區別是,稍後我會得到錯誤)。在啓動任何dao請求之前,我啓用了Hibernate stats來檢查打開會話的數量。處理請求後,所有會話都會關閉。我正在使用OpenSessionInViewFilter,因此每個請求都有一個會話。

以下是所有文件 web.xml中:

<?xml version="1.0" encoding="ISO-8859-1"?> 
<!DOCTYPE web-app 
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" 
    "http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"> 
<web-app> 
    <context-param> 
     <param-name>contextConfigLocation</param-name> 
     <param-value> 
      /WEB-INF/applicationContext-security.xml 
      /WEB-INF/spring-database.xml 
      /WEB-INF/application-action.xml 
      /WEB-INF/newbeans.xml 
     </param-value> 
    </context-param> 
    <filter> <!-- Get spring to keep the session open for the whole request, so Hibernates lazy loads work --> 
     <filter-name>openSessionInViewFilter</filter-name> 
     <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>openSessionInViewFilter</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

    <filter> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>springSecurityFilterChain</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

    <!-- - Loads the root application context of this web app at startup. - 
     The application context is then available via - WebApplicationContextUtils.getWebApplicationContext(servletContext). --> 
    <listener> 
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> 
    </listener> 

    <listener> 
     <listener-class> 
      net.sf.navigator.menu.MenuContextListener</listener-class> 
    </listener> 

    <context-param> 
     <param-name>log4jConfigLocation</param-name> 
     <param-value>/WEB-INF/classes/log4j.properties</param-value> 
    </context-param> 

    <listener> 
     <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class> 
    </listener> 
    <filter> 
     <filter-name>struts2</filter-name> 
     <filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class> 
    </filter> 
    <filter-mapping> 
     <filter-name>struts2</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 
</web-app> 

Spring和Hibernate文件

<beans xmlns="http://www.springframework.org/schema/beans" 
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
       xmlns:aop="http://www.springframework.org/schema/aop" 
       xmlns:tx="http://www.springframework.org/schema/tx" 
       xsi:schemaLocation=" 
       http://www.springframework.org/schema/beans 
       http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
       http://www.springframework.org/schema/tx 
       http://www.springframework.org/schema/tx/spring-tx-3.0.xsd 
       http://www.springframework.org/schema/aop 
       http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> 
    <tx:annotation-driven/> 
    <bean id="myDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> 
     <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" /> 
     <property name="url" value="jdbc:oracle:thin:@192.168.1.118:1521:BAADB" /> 
     <property name="username" value="htwork" /> 
     <property name="password" value="*****" /> 
    </bean>   
    <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
     <property name="dataSource" ref="myDataSource" /> 
     <property name="annotatedClasses"> 
      <list> 
       <value>com.tda.ht.bean.SerialNumbers</value> 
       <value>com.tda.ht.bean.Bunos</value> 
       <value>com.tda.ht.bean.Tms</value> 
       <value>com.tda.ht.bean.Custodian</value> 
       <value>com.tda.ht.bean.CMISConfEntry</value> 
       <value>com.tda.ht.bean.HeloTrackCurrentBunoConf</value> 
       <value>com.tda.ht.bean.RepairBean</value> 
       <value>com.tda.ht.bean.TDIncorporation</value> 
       <value>com.tda.ht.bean.Miscellaneous</value> 
       <value>com.tda.ht.bean.Inspection</value> 
       <value>com.tda.ht.bean.HTComponentHistory</value> 
       <value>com.tda.ht.bean.Component</value> 
       <value>com.tda.baa.dao.TransferRequest</value> 
       <value>com.tda.baa.dao.UsersTable</value> 
       <value>com.tda.baa.dao.UserRoles</value> 
       <value>com.tda.ht.bean.EHRCurrentBunoConf</value> 
       <value>com.tda.ht.bean.SRCCurrentBunoConf</value> 
       <value>com.tda.ht.bean.ASRCurrentBunoConf</value> 
       <value>com.tda.ht.bean.ASRSubCurrentBunoConf</value> 
       <value>com.tda.ht.bean.ASRTree</value> 
       <value>com.tda.ht.bean.PMICTree</value> 
      </list> 
     </property> 
     <property name="hibernateProperties"> 
      <props> 
       <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop> 
       <prop key="hibernate.show_sql">true</prop> 
       <prop key="hibernate.generate_statistics">true</prop> 
       <prop key="hibernate.c3p0.min_size">5</prop> 
       <prop key="hibernate.c3p0.max_size">20</prop> 
       <prop key="hibernate.c3p0.timeout">300</prop> 
       <prop key="hibernate.c3p0.max_statements">50</prop> 
       <prop key="hibernate.c3p0.idle_test_period">3000</prop> 
      </props> 
     </property> 
    </bean> 
    <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> 
     <property name="sessionFactory" ref="sessionFactory"/> 
    </bean> 

    <bean id="componentDAO" class="com.tda.ht.dao.component.ComponentDAOImpl"> 
     <property name="sessionFactory" ref="sessionFactory"></property> 
    </bean> 

    <bean id="componentBusiness" class="com.tda.ht.business.component.ComponentBusinessImpl"> 
     <property name="iCompDAO" ref="componentDAO"></property> 
    </bean> 
</beans> 

行動方法調用請求componentBusiness - 這是由Spring管理

public String displayHeader() { 
    Component c = componentBusiness.getComponentByPartNumber(partNumber); 
    return SUCCESS; 
} 

業務層

package com.tda.ht.business.component; 
import java.util.List; 
import org.springframework.transaction.annotation.Transactional; 
import com.tda.ht.bean.Component; 
import com.tda.ht.dao.component.IComponentDAO; 

public class ComponentBusinessImpl implements IComponentBusiness { 
    private IComponentDAO iCompDAO; 

    //service layer method, transactions handled by spring 
    @Transactional(readOnly = true) 
    public Component getComponentByPartNumber(String partNumber) { 
     // TODO Auto-generated method stub 
     return iCompDAO.getComponentByPartNumber(partNumber); 
    } 
} 

DAO層

public class ComponentDAOImpl implements IComponentDAO { 

SessionFactory sessionFactory; 

protected static org.apache.log4j.Logger log = Logger 
       .getLogger(ComponentDAOImpl.class); 

//dao method called from service layer 

@Override 
public Component getComponentByPartNumber(String partNumber) { 
    String[] arguments = { partNumber }; 

    long open = sessionFactory.getStatistics().getSessionOpenCount(); 
    long close = sessionFactory.getStatistics().getSessionCloseCount(); 

     log.error("Open " + open + " Close " + close); 
     Session s = sessionFactory.getCurrentSession(); 

     log.error(" SESSION IS " + s.hashCode()); 

     try { 
      Query q = s.createQuery("Select entry from Component as entry where entry.partNumber = ?"); 

      q.setParameter(0, partNumber); 
      List<Component> list = q.list(); 

      if (list.size() > 0) 
       return list.get(0); 

      return null; 
     }catch (Exception e) { 
      e.printStackTrace(); 
     }finally { 
      //s.close(); 
     } 
    return null; 
    }   
} 

在DAO層,我收集打開和關閉會話統計,所不同的是從來沒有超過4,因爲我有模擬4用戶。看起來像所有的會議正在關閉。處理請求時。如果我不使用spring並通過自己的SessionFactory管理Hibernate,打開和關閉會話,那麼一切正常,並且沒有錯誤。 我很困惑,因爲我沒有看到任何會話被泄露,任何指針將不勝感激。

+1

您使用的是什麼版本的Hibernate?它說你在你的XML中使用Hibernate3對象,但是你真的擁有Hibernate3的jar嗎?如果你分割你的代碼塊,併爲每個文件分別設置一個代碼塊,它也會使閱讀更容易。 – JamesENL

+0

stacktrace是發生錯誤的地方,但你有不完整的堆棧跟蹤,所以你有時間和努力來自己解決這個錯誤。順便說一句春天使用模板來支持與休眠交易。 –

回答

2

DriverManagerDataSource並不意味着在生產中使用,在生產中你想要使用連接池,DriverManagerDataSource不是連接池,我建議使用像Tomcat JDBC或Commons DBCP這樣的連接池。

您的hibernate.c3p0設置無用,因爲您正在使用Spring配置和注入數據源,因此這些屬性將被忽略。

最後,你的DAO代碼(可能是)有缺陷,你不應該抓住併吞下Exception,因爲這可能會破壞正確的tx管理。

如果您希望Log4j正確初始化,則應在ContextLoaderListener之前配置一個最終的無關的提示Log4jConfigListener。雖然我懷疑你需要它,因爲log4j.xml在yuor classpath上,所以Log4J可能已經啓動了。

+0

謝謝。使用連接池替換DriverManagerDataSource似乎解決了這個問題。 DAO層中的異常塊僅用於調試目的,而我正在努力解決這些錯誤。一旦我完成,我不打算這樣做。拋棄我的是我可以模擬一個或兩個用戶連續請求沒有任何問題。再次感謝。 – user3605072

相關問題