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
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&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>
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&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().
<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 回調的方法管理數據庫.
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 能不能解決問題 還需要進一步檢驗。下回分解。
posted on 2010-12-20 11:49 游雯 閱讀(3697) 評論(0) 編輯 收藏 所屬分類: Java技術