目錄
一.問題
- 程序如果長時間不進行數據庫操作,那麼數據源中的 Connection 很可能已經斷開。其原因有可能是防火牆,或者連接的數據庫設置的超時時間。
二.問題總結:
- 當數據庫連接池中的連接被創建而長時間不使用的情況下,該連接會自動回收並失效,但客戶端並不知道,在進行數據庫操作時仍然使用的是無效的數據庫連接,這樣,就導致客戶端程序報“ java.sql.SQLException: Io 異常: Connection reset” 或“java.sql.SQLException 關閉的連接”異常。
三.Spring+IBatis解決方式
- 在配置數據源後面加上
<property name="validationQuery" value="select * from dual"/>
- 配置後,客戶端在使用一個無效的連接時會先對該連接進行測試,如果發現該連接已經無效,則重新從連接池獲取有效數據庫連接來使用
- 程序中採用的是Spring+IBatis,數據源配置如下:在 applicationContext.xml中如下設置:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<property name="maxActive" value="100"/>
<property name="maxIdle" value="30"/>
<property name="maxWait" value="1000"/>
<property name="defaultAutoCommit" value="true"/>
</bean>
- 經過查找資料和分析,得出該問題主要是由於連接時間過長,失效所致,將以上配置修改如下:
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
<property name="maxActive" value="100"/>
<property name="maxIdle" value="30"/>
<property name="maxWait" value="1000"/>
<property name="defaultAutoCommit" value="true"/>
<property name="validationQuery" value="select * from dual"/>
</bean>
五.c3p0解決的辦法是:
- 在 applicationContext.xml中如下設置:
<!-- 數據庫連接聲明 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
destroy-method="close">
<property name="driverClass" value="com.alibaba.china.jdbc.SimpleDriver" />
<!-- <property name="driverClass" value="oracle.jdbc.OracleDriver" /> -->
<property name="jdbcUrl" value="jdbc:oracle:thin:@202.116.70.180:61166:orcl" />
<!-- 每60秒檢查所有連接池中的空閒連接。Default: 0 -->
<property name="idleConnectionTestPeriod" value="60" />
<!--如果設爲true那麼在取得連接的同時將校驗連接的有效性。Default: false -->
<property name="testConnectionOnCheckin" value="true" />
<!--c3p0將建一張名爲Test的空表,並使用其自帶的查詢語句進行測試。如果定義了這個參數那麼 屬性preferredTestQuery將被忽略。你不能在這張Test表上進行任何操作,它將只供c3p0測試使用。Default: null -->
<property name="automaticTestTable" value="Test" />
<property name="properties">
<props>
<prop key="clientEncoding">GBK</prop>
<prop key="serverEncoding">CP1252</prop>
<prop key="user">WDS</prop>
<prop key="password">HelloOracle</prop>
</props>
</property>
</bean>
注意:
- 配置項一定要作爲 <bean> 的子元素,而不能做爲 <properties> 的子元素,否則不起作用。
擴展:
DBCP連接池:
- 在applicationContext.xml中
<!-- 數據源1 -->
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://192.168.0.109:3306/test?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
<!--maxActive: 最大連接數量-->
<property name="maxActive" value="150"/>
<!--minIdle: 最小空閒連接-->
<property name="minIdle" value="5"/>
<!--maxIdle: 最大空閒連接-->
<property name="maxIdle" value="20"/>
<!--initialSize: 初始化連接-->
<property name="initialSize" value="30"/>
<!-- 連接被泄露時是否打印 -->
<property name="logAbandoned" value="true"/>
<!--removeAbandoned: 是否自動回收超時連接-->
<property name="removeAbandoned" value="true"/>
<!--removeAbandonedTimeout: 超時時間(以秒數爲單位)-->
<property name="removeAbandonedTimeout" value="10"/>
<!--maxWait: 超時等待時間以毫秒爲單位 1000等於60秒-->
<property name="maxWait" value="1000"/>
<!-- 在空閒連接回收器線程運行期間休眠的時間值,以毫秒爲單位. -->
<property name="timeBetweenEvictionRunsMillis" value="10000"/>
<!-- 在每次空閒連接回收器線程(如果有)運行時檢查的連接數量 -->
<property name="numTestsPerEvictionRun" value="10"/>
<!-- 1000 * 60 * 30 連接在池中保持空閒而不被空閒連接回收器線程-->
<property name="minEvictableIdleTimeMillis" value="10000"/>
<property name="validationQuery" value="SELECT NOW() FROM DUAL"/>
</bean>
參考:
https://blog.csdn.net/zqd_java/article/details/53738373
http://my.oschina.net/tianzimensheng/blog/65225
http://www.cnblogs.com/younes/archive/2012/06/01/2529483.html
http://www.cnblogs.com/safeking/archive/2007/02/01/637067.html