Hibernate,Spring和c3p0连接池导致JBoss打开太多与数据库的连接

时间:2014-07-01 10:14:17

标签: spring hibernate c3p0 jboss6.x

我的应用程序出现了一个奇怪的问题,它运行在使用Hibernate和Spring的JBoss 6.1上。我也使用c3p0来建立连接池。

我在JBoss下定义了一个数据源。数据源是C3P0PooledDataSource。请注意,maxpoolsize为20,初始池大小也为20。

<mbean code="com.mchange.v2.c3p0.jboss.C3P0PooledDataSource"
      name="jboss.jca:service=DataSourceBinding,name=db/MED_POOLED">

  <attribute name="JndiName">java:db/MED_POOLED</attribute>
  <attribute name="JdbcUrl">jdbc:oracle:thin:@dbhost:1521:SID</attribute>
  <attribute name="DriverClass">oracle.jdbc.driver.OracleDriver</attribute>
  <attribute name="User">xxx</attribute>
  <attribute name="Password">xxx</attribute>
  <attribute name="AutomaticTestTable">POOL_TEST</attribute>          
  <attribute name="CheckoutTimeout">30000</attribute>      
  <attribute name="Description">Pooled Datasource for med</attribute>
  <attribute name="IdleConnectionTestPeriod">180</attribute>     
  <attribute name="InitialPoolSize">20</attribute>  
  <attribute name="MaxPoolSize">20</attribute>   
  <attribute name="MinPoolSize">20</attribute>    
  <attribute name="TestConnectionOnCheckin">true</attribute>       
  <attribute name="MaxIdleTime">3600</attribute>
  <depends>jboss:service=Naming</depends>
</mbean>

在我的spring配置文件中,使用jndi名称检索数据源:

<bean id="defaultDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
    <property name="jndiName"><value>db/MED_POOLED</value></property>
</bean>

然后用于构建LocalSessionFactoryBean

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="defaultDataSource"/>
    <property name="namingStrategy" ref="namingStrategy"/>
    <property name="configLocations">
        <list>
        <value>classpath:hibernate.cfg.xml</value>
        <value>classpath:jbpm.hibernate.cfg.xml</value>
        </list>
    </property>
    <property name="mappingDirectoryLocations">
        <list><value>WEB-INF/classes</value></list>
    </property>
</bean>

在hibernate.cfg.xml中没有定义数据源,因此应该使用org.springframework.orm.hibernate3.LocalSessionFactoryBean的dataSource属性。

当我启动应用程序服务器时,会发生一些奇怪的事情(至少对我来说很奇怪):

  • JBoss启动,我在日志中看到这一行

    [com.mchange.v2.c3p0.jboss.C3P0PooledDataSource]将C3P0 PooledDataSource绑定到名称&#39; java:d​​b / MED_POOLED&#39;。开始......

如果我检查数据库,则会有20个会话。

  • 创建LocalSessionFactoryBean时,Db上存在suddendly 40连接,但在我指定的数据源配置中,最多可创建20个连接。

我认为,在某种程度上,当创建LocalSessionFactoryBean时,数据源会重新初始化,但我不明白为什么,当JBoss启动时,我只有两倍的连接。

你知道发生了什么吗?我的配置有问题吗?

我使用的是JBoss 6.1,最新版本的c3p0(0.9.5),Spring 3.0.3.RELEASE和Hibernate 3.5.3-Final

1 个答案:

答案 0 :(得分:1)

有两种可能的方式,连接数可能是预期池大小的两倍。

  1. 您可能会以某种方式初始化两个c3p0 DataSource;
  2. 您可能通过调用dataSource.getConnection( user, password )
  3. 获取两个不同身份验证的Connections

    检查这两种可能性的最简单方法是通过JMX:如果C3P0Registry MBean显示两个不同的PooledDataSource,那就是你的问题。否则,在DataSource中查找属性numUserPools:它是两个吗?

    我先检查这些可能性。

    [如果您无权访问JMX,您可以通过从名为com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource的记录器中查找INFO级别的日志条目,以及以&#34;开头的条目来查看是否已初始化多个DataSource。初始化c3p0池......&#34;然后显示正在初始化的池的配置。]

    另一种可能性是,由于某种原因,您的应用程序是热重新部署的,但是当应用程序的旧实例被拆除时,您的c3p0 DataSource尚未关闭。如果c3p0的类由多个不同的ClassLoader加载,那么调试将更难以导致奇怪的行为。 (我不太了解JBoss是否/如何实现热重新部署以了解这是否可能是一个问题。)避免这种问题的一种方法是确保c3p0的jar文件在应用程序服务器级别可用,而不是任何特定应用程序的子级,然后将c3p0 [0.9.5]配置参数contextClassLoaderSource设置为library,请参阅http://www.mchange.com/projects/c3p0/#contextClassLoaderSource