1. 程式人生 > >Spring框架中獲取連線池的方式

Spring框架中獲取連線池的方式

1、連線池概述

  資料庫連線是一種關鍵的有限的昂貴的資源,這一點在多使用者的網頁應用程式中體現得尤為突出。對資料庫連線的管理能顯著影響到整個應用程式的伸縮性和健壯性,影響到程式的效能指標。資料庫連線池正是針對這個問題提出來的。 
   
  資料庫連線池負責分配、管理和釋放資料庫連線,它允許應用程式重複使用一個現有的資料庫連線,而再不是重新建立一個;釋放空閒時間超過最大空閒時間的資料庫連線來避免因為沒有釋放資料庫連線而引起的資料庫連線遺漏。這項技術能明顯提高對資料庫操作的效能。 
   
  資料庫連線池在初始化時將建立一定數量的資料庫連線放到連線池中,這些資料庫連線的數量是由最小資料庫連線數來設定的。無論這些資料庫連線是否被使用,連線池都將一直保證至少擁有這麼多的連線數量。連線池的最大資料庫連線數量限定了這個連線池能佔有的最大連線數,當應用程式向連線池請求的連線數超過最大連線數量時,這些請求將被加入到等待佇列中。資料庫連線池的最小連線數和最大連線數的設定要考慮到下列幾個因素: 
  1) 最小連線數是連線池一直保持的資料庫連線,所以如果應用程式對資料庫連線的使用量不大,將會有大量的資料庫連線資源被浪費; 
  2) 最大連線數是連線池能申請的最大連線數,如果資料庫連線請求超過此數,後面的資料庫連線請求將被加入到等待佇列中,這會影響之後的資料庫操作。 
  3) 如果最小連線數與最大連線數相差太大,那麼最先的連線請求將會獲利,之後超過最小連線數量的連線請求等價於建立一個新的資料庫連線。不過,這些大於最小連線數的資料庫連線在使用完不會馬上被釋放,它將被放到連線池中等待重複使用或是空閒超時後被釋放。

2、spring中常用的連線池

spring中常用的連線池有:C3P0、DBCP、Proxool、獲取JNDI資料來源等

C3P0比較耗費資源,效率方面可能要低一點。 
DBCP在實踐中存在BUG,在某些種情會產生很多空連線不能釋放,Hibernate3.0已經放棄了對其的支援。 
Proxool的負面評價較少,現在比較推薦它,而且它還提供即時監控連線池狀態的功能,便於發現連線洩漏的情況。 
   
不管通過何種持久化技術,都必須通過資料連線訪問資料庫,在Spring中,資料連線是通過資料來源獲得的。在以往的應用中,資料來源一般是Web應用伺服器提供的。在Spring中,你不但可以通過JNDI獲取應用伺服器的資料來源,也可以直接在Spring容器中配置資料來源,此外,你還可以通過程式碼的方式建立一個數據源,以便進行無依賴的單元測試。

3、DBCP資料來源

DBCP類包位於 /lib/jakarta-commons/commons-dbcp.jar,DBCP是一個依賴Jakarta commons-pool物件池機制的資料庫連線池,所以在類路徑下還必須包括/lib/jakarta-commons/commons-pool.jar。下面是使用DBCP配置Oracle資料來源的配置片斷:

<beanid="dbcp_dataSource"class="org.apache.commons.dbcp.BasicDataSource">

    <propertyname="driverClassName"value="oracle.jdbc.driver.OracleDriver"
></property> <propertyname="url"value="jdbc:oracle:thin:@localhost:1521/ssid"></property> <propertyname="username"value="user"></property> <propertyname="password"value="password"></property> <propertyname="initialSize"value="3"></property> <propertyname="maxActive"value="50"></property> <propertyname="maxIdle"value="20"></property> <propertyname="minIdle"value="5"></property> <propertyname="maxWait"value="10"></property> </bean> <!-- DBCP資料來源的屬性說明 initialSize:連線池初始化時的初始連線數 maxActive:連線池的最大值 maxIdle:最大空閒值 minIdle:最小空閒值 maxWait:最大建立連線等待時間 -->

4、C3P0資料來源

C3P0是一個開放原始碼的JDBC資料來源實現專案,它在lib目錄中與hibernate一起釋出,實現了JDBC3和JDBC2擴充套件規範說明的Connection 和Statement 池。C3P0類包位於/lib/c3p0/c3p0-0.9.0.4.jar。下面是使用C3P0配置一個Oracle資料來源:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">

    <propertyname="driverClass"value="oracle.jdbc.driver.OracleDriver"/>

    <propertyname="jdbcUrl"value="jdbc:oracle:thin:@localhost:1521/ssid"/>

    <propertyname="user"value="user"/>

    <propertyname="password"value="password"/>

    <propertyname="initialPoolSize"value="10"/>

    <propertyname="minPoolSize"value="10"/>

    <propertyname="maxPoolSize"value="100"/>

</bean>



<!--  C3P0的配置屬性,通過這些屬性,可以對資料來源進行各種有效的控制:

  acquireIncrement:當連線池中的連線用完時,C3P0一次性建立新連線的數目;

  acquireRetryAttempts:定義在從資料庫獲取新連線失敗後重復嘗試獲取的次數,預設為30;

  acquireRetryDelay:兩次連線中間隔時間,單位毫秒,預設為1000;

  autoCommitOnClose:連線關閉時預設將所有未提交的操作回滾。預設為false;

  automaticTestTable: C3P0將建一張名為Test的空表,並使用其自帶的查詢語句進行測試。如果定義了這個引數,那麼屬性preferredTestQuery將被忽略。你不能在這張Test表上進行任何操作,它將中為C3P0測試所用,預設為null;

  breakAfterAcquireFailure:獲取連線失敗將會引起所有等待獲取連線的執行緒丟擲異常。但是資料來源仍有效保留,並在下次調 用getConnection()的時候繼續嘗試獲取連線。如果設為true,那麼在嘗試獲取連線失敗後該資料來源將申明已斷開並永久關閉。預設為 false;

  checkoutTimeout:當連線池用完時客戶端呼叫getConnection()後等待獲取新連線的時間,超時後將丟擲SQLException,如設為0則無限期等待。單位毫秒,預設為0;

  connectionTesterClassName:通過實現ConnectionTester或QueryConnectionTester的類來測試連線,類名需設定為全限定名。預設為 com.mchange.v2.C3P0.impl.DefaultConnectionTester;

  idleConnectionTestPeriod:隔多少秒檢查所有連線池中的空閒連線,預設為0表示不檢查;

  initialPoolSize:初始化時建立的連線數,應在minPoolSize與maxPoolSize之間取值。預設為3;

  maxIdleTime:最大空閒時間,超過空閒時間的連線將被丟棄。為0或負數則永不丟棄。預設為0;

  maxPoolSize:連線池中保留的最大連線數。預設為15;

  maxStatements:JDBC的標準引數,用以控制資料來源內載入的PreparedStatement數量。但由於預快取的Statement屬於單個Connection而不是整個連線池。所以設定這個引數需要考慮到多方面的因素,如果maxStatements與 maxStatementsPerConnection均為0,則快取被關閉。預設為0;

  maxStatementsPerConnection:連線池內單個連線所擁有的最大快取Statement數。預設為0;

  numHelperThreads:C3P0是非同步操作的,緩慢的JDBC操作通過幫助程序完成。擴充套件這些操作可以有效的提升效能,通過多執行緒實現多個操作同時被執行。預設為3;

  preferredTestQuery:定義所有連線測試都執行的測試語句。在使用連線測試的情況下這個引數能顯著提高測試速度。測試的表必須在初始資料來源的時候就存在。預設為null;

  propertyCycle:使用者修改系統配置引數執行前最多等待的秒數。預設為300;

  testConnectionOnCheckout:因效能消耗大請只在需要的時候使用它。如果設為true那麼在每個connection提交的時候都將校驗其有效性。建議使用idleConnectionTestPeriod或automaticTestTable

等方法來提升連線測試的效能。預設為false;

  testConnectionOnCheckin:如果設為true那麼在取得連線的同時將校驗連線的有效性。預設為false-->

5、Proxool資料來源

Proxool是一種Java資料庫連線池技術。sourceforge下的一個開源專案,這個專案提供一個健壯、易用的連線池,最為關鍵的是這個連線池提供監控的功能,方便易用,便於發現連線洩漏的情況。

<bean id="proxool_dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">

      <property name="driver-class" value="oracle.jdbc.driver.OracleDriver"/>

      <property name="driver-url" value="jdbc:oracle:thin:@localhost:1521/ssid"/>

       <property name="user" value="user"/>

       <property name="password" value="password"/>



      <!-- 測試的SQL執行語句 -->

      <property name="houseKeepingTestSql" value="select CURRENT_DATE"/>

      <!-- 最少保持的空閒連線數(預設2個) -->

      <property name="prototypeCount" value="2"/>

      <!-- proxool自動偵察各個連線狀態的時間間隔(毫秒),偵察到空閒的連線就馬上回收,超時的銷燬預設30秒) -->

      <property name="houseKeepingSleepTime" value="30"/>

      <!-- 最大活動時間(超過此時間執行緒將被kill,預設為5分鐘) -->

      <property name="maximumActiveTime" value="300"/>

      <!-- 連線最長時間(預設為4個小時) -->

      <property name="maximumConnectionLifetime" value="30"/>

      <!-- 最小連線數(預設2個) -->

      <property name="minimumConnectionCount" value="10"/>

      <!-- 最大連線數(預設5個) -->

      <property name="maximumConnectionCount" value="30"/>

      <!-- 同時最大連線數 -->

      <property name="simultaneousBuildThrottle" value="10"/>

</bean>

 這種方式需要把使用者名稱和密碼寫在連線串裡面,ProxoolDataSource類提供的user,password屬性似乎沒有什麼用。無論提供什麼,它都會以空使用者名稱、密碼去連線資料庫,但是user,password兩個屬性必須設定,否則hibernate會報空指標錯誤。

6、獲取JNDI資料來源

如果應用配置在高效能的應用伺服器(如WebLogic或Websphere等)上,我們可能更希望使用應用伺服器本身提供的資料來源。應用伺服器的資料來源使用JNDI開放呼叫者使用,Spring為此專門提供引用JNDI資源的JndiObjectFactoryBean類。一個簡單的配置片段:

<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">       
    <property name="jndiName" value="java:comp/env/jdbc/sample"/>       
</bean> 

使用jee名稱空間引用JNDI資料來源的配置片段:

<!--Spring 為獲取J2EE資源提供了一個jee名稱空間,通過jee名稱空間,可以有效地簡化J2EE資源的引用-->
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:jee=http://www.springframework.org/schema/jee 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:p="http://www.springframework.org/schema/p" 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.2.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd 
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
     http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

    <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/sample"/>

</beans>

7、spring的資料來源實現類(DriverManagerDataSource)

Spring本身也提供了一個簡單的資料來源實現類DriverManagerDataSource ,它位於org.springframework.jdbc.datasource包中。這個類實現了javax.sql.DataSource介面,但它並沒有提供池化連線的機制,每次呼叫getConnection()獲取新連線時,只是簡單地建立一個新的連線。因此,這個資料來源類比較適合在單元測試或簡單的獨立應用中使用,因為它不需要額外的依賴類。

<!--配置-->
<bean id=”dataSource” class=”org.springframework.jdbc.datasource.DriverManagerDataSource” destroy-method=”close”>
    <property name=”driverClassName” value= oracle.jdbc.driver.OracleDriver ” />
    <property name=”url” value=”jdbc:oracle:thin:@localhost:1521:orcl ” />
    <property name=”username” value=”root” />
    <property name=”password” value=”1234″ />
</bean>

<!--直接使用 -->
DriverManagerDataSource ds = new DriverManagerDataSource ();       
ds.setDriverClassName("com.mysql.jdbc.Driver");       
ds.setUrl("jdbc:mysql://localhost:3306/sampledb");       
ds.setUsername("root");       
ds.setPassword("1234");       
Connection actualCon = ds.getConnection();