Spring+Hibernate:在applicationContext.xml中配置C3P0参数说明

 

背景:
在项目中遇到下面这个exception
Exception occurred while logging on

Hibernate operation: Cannot open connection; uncategorized SQLException
for SQL [ ??? ];
SQL state [
null ]; error code [ 0 ]; An SQLException was provoked by the following failure:
com.mchange.v2.resourcepool.ResourcePoolException: Attempted to use a closed or
broken resource pool; nested exception is java.sql.SQLException: An SQLException was
provoked by the following failure: com.mchange.v2.resourcepool.ResourcePoolException:
Attempted to use a closed or broken resource pool

分析:
看字面的意思,是连接池出问题。因为对spring的连接池配置不熟,所以就找到下面的文章。
<引用: http://hi.baidu.com/javazyw/blog/item/4e668fc7e3557ac039db49c3.html>

  1 <? xml version="1.0" encoding="UTF-8" ?>
  2 < beans xmlns ="http://www.springframework.org/schema/beans"
  3     xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
  4     xmlns:jee ="http://www.springframework.org/schema/jee"
  5     xsi:schemaLocation ="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
  6             http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.0.xsd" >
  7     < bean id ="dataSource"
  8         class ="com.mchange.v2.c3p0.ComboPooledDataSource"
  9         destroy-method ="close" >
10         < property name ="driverClass" >
11             < value > com.mysql.jdbc.Driver </ value >
12         </ property >
13         < property name ="jdbcUrl" >
14             < value > jdbc:mysql://192.168.3.110:3306/DBName?useUnicode=true &amp; characterEncoding=GBK </ value >
15         </ property >
16         < property name ="user" >
17             < value > root </ value >
18         </ property >
19         < property name ="password" >
20             < value > root </ value >
21         </ property >
22
23 <!-- 连接池中保留的最小连接数。 -->
24         < property name ="minPoolSize" >
25             < value > 5 </ value >
26         </ property >
27
28 <!-- 连接池中保留的最大连接数。Default: 15 -->
29         < property name ="maxPoolSize" >
30             < value > 30 </ value >
31         </ property >
32
33 <!-- 初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
34         < property name ="initialPoolSize" >
35             < value > 10 </ value >
36         </ property >
37
38 <!-- 最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 -->
39         < property name ="maxIdleTime" >
40             < value > 60 </ value >
41         </ property >
42
43 <!-- 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
44         < property name ="acquireIncrement" >
45             < value > 5 </ value >
46         </ property >
47
48 <!-- JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements
49 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。
50 如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 -->
51         < property name ="maxStatements" >
52             < value > 0 </ value >
53         </ property >
54
55 <!-- 每60秒检查所有连接池中的空闲连接。Default: 0 -->
56         < property name ="idleConnectionTestPeriod" >
57             < value > 60 </ value >
58         </ property >
59
60 <!-- 定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
61         < property name ="acquireRetryAttempts" >
62             < value > 30 </ value >
63         </ property >
64
65 <!-- 获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效
66 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试
67 获取连接失败后该数据源将申明已断开并永久关闭。Default: false -->
68         < property name ="breakAfterAcquireFailure" >
69             < value > true </ value >
70         </ property >
71
72 <!-- 因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的
73 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable
74 等方法来提升连接测试的性能。Default: false -->
75         < property name ="testConnectionOnCheckout" >
76             < value > false </ value >
77         </ property >
78     </ bean >
79     <!-- Hibernate SessionFactory -->
80     < bean id ="sessionFactory"
81         class ="org.springframework.orm.hibernate3.LocalSessionFactoryBean" >
82         < property name ="dataSource" >
83             < ref local ="dataSource" />
84         </ property >
85         < property name ="mappingResources" >
86             < list >
87                 < value > com/xh/hibernate/vo/User.hbm.xml </ value >
88             </ list >
89         </ property >
90         < property name ="hibernateProperties" >
91             < props >
92                 < prop key ="hibernate.dialect" > org.hibernate.dialect.MySQLDialect </ prop >
93                 < prop key ="hibernate.show_sql" > true </ prop >
94                 < prop key ="hibernate.generate_statistics" > true </ prop >
95                 < prop key ="hibernate.connection.release_mode" > auto </ prop >
96                 < prop key ="hibernate.autoReconnect" > true </ prop >
97             </ props >
98         </ property >
99     </ bean >
100 </ beans >

应该是配置的原因。然后有找到这篇个说明
<引用:http://home.bendixinwen.cn:8080/blog/2010/01/27/1264560312821.html>
解决这个异常需要修改设置成如下:

< property name ="acquireRetryAttempts" >
   
< value > 30 </ value >
</ property >
< property name ="acquireRetryDelay" >
   
< value > 100 </ value >
</ property >
< property name ="breakAfterAcquireFailure" >
   
< value > false </ value >
</ property >
- acquireRetryAttempts
Default: 30
Defines how many times c3p0 will try to acquire a new Connection from the database before giving up.
If this value is less than or equal to zero, c3p0 will keep trying to fetch a Connection indefinitely

- acquireRetryDelay
Default: 1000
Milliseconds, time c3p0 will wait between acquire attempts.

- breakAfterAcquireFailure
Default: false
If true, a pooled DataSource will declare itself broken and be permanently closed
if a Connection cannot be obtained from the database after making acquireRetryAttempts to acquire one.
If false, failure to obtain a Connection will cause all Threads waiting for the pool to acquire a Connection
to throw an Exception, but the DataSource will remain valid, and will attempt to acquire again following a
call to getConnection().

再分析:
为什么会说 Attempted to use a closed or broken resource pool,应该是有链接没关闭。因为一直对<session.save>和<geHibernateTemplate().save> 这两种DAO实现方式不理解。找到下面这篇文章
<引用:http://jeoff.blog.51cto.com/186264/133434>
1 自动生成hibernate配置文件的时候,会在dao层用到getSession()方法来操作数据库记录,但是他还有个方法getHibernateTemplate(),这两个方法究竟有什么区别呢?
2 1.使用getSession()方法你只要继承sessionFactory,而使用getHibernateTemplate()方法必须继承 HibernateDaoSupport当然包括sessionFactory,这点区别都不是特别重要的,下面这些区别就很重要了
3 2.getSession()方法是没有经过spring包装的,spring会把最原始的session给你,在使用完之后必须自己调用相应的 close方法,而且也不会对声明式事务进行相应的管理,一旦没有及时关闭连接,就会导致数据库连接池的连接数溢出,getHibernateTemplate()方法是经过spring封装的,例如添加相应的声明式事务管理,由spring管理相应的连接。
4 在实际的使用过程中发现的确getHibernateTemplate()比getSession()方法要好很多,但是有些方法在getHibernateTemplate()并没有提供,这时我们用HibernateCallback 回调的方法管理数据库.


看看黑体标注的那句话,再看看程序代码会发现确实有很多使用session方式的DAO在最后没有关闭。root cause应该就是他了。

总结:

1. 是用session实现DAO,必须要在最后关闭session,不然会导致连接池链接溢出
2.可以使用 set breakAfterAcquireFailure =false 来规避这个问题。

尾巴:
set breakAfterAcquireFailure =false 能不能解决问题 还需要进一步检验。下回分解。

 

文章出处:http://www.blogjava.net/unilobster/articles/341148.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值