細心!用心!耐心!

          吾非文人,乃市井一俗人也,讀百卷書,跨江河千里,故申城一游; 一兩滴辛酸,三四年學業,五六點粗墨,七八筆買賣,九十道人情。

          BlogJava 聯系 聚合 管理
            1 Posts :: 196 Stories :: 10 Comments :: 0 Trackbacks

          簡單的MySQL連接池

          1. <Resource type="javax.sql.DataSource" 
          2.             name="jdbc/TestDB" 
          3.             factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          4.             driverClassName="com.mysql.jdbc.Driver" 
          5.             url="jdbc:mysql://localhost:3306/mysql" 
          6.             username="mysql_user" 
          7.             password="mypassword123" 
          8. /> 
          第一個我們需要注意的屬性是factory="org.apache.tomcat.jdbc.pool.DataSourceFactory".

           

          當tomcat讀到type="javax.sql.DataSource"屬性時會自動重新安裝DBCP,除非你指定不同的factory。factory object 本身就是創建和配置連接池的。

          在Apache Tomcat中有兩種方式配置 Resource elements

          配置全局連接池

          編輯conf/server.xml

          1. <GlobalNamingResources> 
          2.   <Resource type="javax.sql.DataSource" 
          3.             name="jdbc/TestDB" 
          4.             factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          5.             driverClassName="com.mysql.jdbc.Driver" 
          6.             url="jdbc:mysql://localhost:3306/mysql" 
          7.             username="mysql_user" 
          8.             password="mypassword123" 
          9. /> 
          10. </GlobalNamingResources> 

          然后你需要創建一個ResourceLink element使這個連接池對于web應用是可用的。如果你想要用同一個名字讓連接池對于所有的應用有效,最簡單的方法就是編輯conf/context.xml文件

           

          1. <Context> 
          2.   <ResourceLink type="javax.sql.DataSource" 
          3.                 name="jdbc/LocalTestDB" 
          4.                 global="jdbc/TestDB" 
          5. /> 
          6. <Context> 

          注意,如果你不想要全局的連接池,可以從server.xml移除Resource element到你的web應用的context.xml 文件。

           

          然后從剛配置好的連接池中獲得連接,簡單java代碼:

          1. Context initContext = new InitialContext(); 
          2. Context envContext  = (Context)initContext.lookup("java:/comp/env"); 
          3. DataSource datasource = (DataSource)envContext.lookup("jdbc/LocalTestDB"); 
          4. Connection con = datasource.getConnection(); 

           

          使用java很簡單

          還可以使用Java syntax

          1. DataSource ds = new DataSource(); 
          2. ds.setDriverClassName("com.mysql.jdbc.Driver"); 
          3. ds.setUrl("jdbc:mysql://localhost:3306/mysql"); 
          4. ds.setUsername("root"); 
          5. ds.setPassword("password"); 
          或者分離出連接池的屬性

           

          1. PoolProperties pp = new PoolProperties(); 
          2. pp.setDriverClassName("com.mysql.jdbc.Driver"); 
          3. pp.setUrl("jdbc:mysql://localhost:3306/mysql"); 
          4. pp.setUsername("root"); 
          5. pp.setPassword("password"); 
          6. DataSource ds = new DataSource(pp); 
          所有的屬性我們可以在XML中通過factory object也可以直接使用PoolProperties或者DataSource objects設置為有效

           

          設置連接池

          我們將使用下面這些屬性設置連接池

          •    initialSize
          •     maxActive
          •     maxIdle
          •     minIdle

          去了解這些屬性是很重要的,它們看起來很明顯但又有一些神秘

          1. <Resource type="javax.sql.DataSource" 
          2.             name="jdbc/TestDB" 
          3.             factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          4.             driverClassName="com.mysql.jdbc.Driver" 
          5.             url="jdbc:mysql://localhost:3306/mysql" 
          6.             username="mysql_user" 
          7.             password="mypassword123" 
          8.             initialSize="10" 
          9.             maxActive="100" 
          10.             maxIdle="50" 
          11.             minIdle="10" 
          12.             /> 

          initialSize=10 設置連接池建立時連接的數目

           

          • 當連接池定義在GlobalNamingResources中,連接池在Tomcat啟動時創鍵
          • 當連接池定義在Context中,連接池在第一次查找JNDI時創建

          maxActive=100 連接數據庫的最大連接數。這個屬性用來限制連接池中能夠打開連接的數量,可以方便數據庫做連接容量規劃。

          minIdle=10  連接池中存在的最小連接數目。連接池中連接數目可以變很少,如果使用了maxAge屬性,有些空閑的連接會被關閉因為離它最近一次連接的時間過去太久了。但是,我們看到的打開的連接不會少于minIdle。

          maxIdle屬性有一點麻煩。它的不同的行為取決于是否使用了pool sweeper。pool sweeper是一個可以在連接池正在使用的時候測試空閑連接和重置連接池大小的后臺線程。還負責檢測連接泄露。pool sweeper 通過如下方式定義的:

          1. public boolean isPoolSweeperEnabled() { 
          2.         boolean timer = getTimeBetweenEvictionRunsMillis()>0; 
          3.         boolean result = timer && (isRemoveAbandoned() && getRemoveAbandonedTimeout()>0); 
          4.         result = result || (timer && getSuspectTimeout()>0);  
          5.         result = result || (timer && isTestWhileIdle() && getValidationQuery()!=null); 
          6.         return result; 
          7.     } 

          sweepertimeBetweenEvictionRunsMillis milliseconds運行一次。

           

          maxIdle定義如下

          • Pool sweeper關閉,如果空閑連接池大于maxIdle,返回的連接將被關閉。
          • Pool sweeper開啟,空閑的連接數可以超過maxIdle,但如果連接空閑的時間已經超過minEvictableIdleTimeMillis,能縮小到minIdle。聽起來很奇怪連接池為什么不關閉連接當空閑連接數量大于maxIdle。想想下面的情況:  
          1. 100個線程處理100個并發請求   
          2. 在一個請求中每個線程請求一個連接3次 

          在這種場景下,如果我們設置maxIdle=50,那么我們會關閉和打開50*3的連接數。這樣增加了數據庫的負重并且減慢了應用的速度。當達到連接高峰時,我們希望能夠充分利用連接池中的所有連接。因此,我們強烈希望打開pool sweeper 。我們將在下一個部分探討具體的事項。我們在這里額外說明maxAge這個屬性。maxAge定義連接能夠打開或者存在的時間,單位為毫秒。當一個連接返回到了連接池,如果這個連接已經使用過,并且距離它第一次被使用的時間大于maxAge時,這個連接會被關閉。

          正如我們所看到的 isPoolSweeper算法實現,sweeper 將會被打開,當以下任一條件滿足時

          • timeBetweenEvictionRunsMillis>0 AND removeAbandoned=true ANDremoveAbandonedTimeout>0
          • timeBetweenEvictionRunsMillis>0 AND suspectTimeout>0
          • timeBetweenEvictionRunsMillis>0 AND testWhileIdle=true AND validationQuery!=null

                        As of version 1.0.9 the following condition has been added

          • timeBetweenEvictionRunsMillis>0 AND minEvictableIdleTimeMillis>0

                       (timer && getMinEvictableIdleTimeMillis()>0);

          因此設置最理想的連接池,我們最好修改我們的配置滿足這些條件

          1. <Resource type="javax.sql.DataSource" 
          2.             name="jdbc/TestDB" 
          3.             factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          4.             driverClassName="com.mysql.jdbc.Driver" 
          5.             url="jdbc:mysql://localhost:3306/mysql" 
          6.             username="mysql_user" 
          7.             password="mypassword123" 
          8.             initialSize="10" 
          9.             maxActive="100" 
          10.             maxIdle="50" 
          11.             minIdle="10" 
          12.             suspectTimeout="60" 
          13.             timeBetweenEvictionRunsMillis="30000" 
          14.             minEvictableIdleTimeMillis="60000" 
          15.             /> 

           

          有效的連接

          數據庫連接池提出了一個挑戰,因為連接池中的連接會過時。這是常有的事,要么數據庫,或者可能是連接池和數據庫中的一個設備,連接超時。唯一確定會話連接是活躍的真正辦法是使連接在服務器和數據庫做一個來回訪問。在Java 6中,JDBC API處理驗證連接是否是有效的方法是通過提供isValid變量來調用java.sql.Connection接口。在此之前,連接池不得不采用執行一個查詢的方法,比如在MySQL上執行SELECT 1.數據庫分析這句查詢很簡單,不需要任何的磁盤訪問。isValid被計劃實施,但 Apache Tomcat 6的連接池,也必須保存對Java 5的兼容性。

          校驗查詢

          校驗查詢會有一些挑戰

          1. 如果它們頻繁使用,會降低系統的性能
          2. 如果使用的間隔太久,會導致連接失效
          3. 如果應用調用setTransactionIsolation并設置autoCommit=false,如果應用再次調用setTransactionIsolation,會產生一個SQLException異常,因為校驗查詢可能在數據庫中已經產生了一個新的transaction。

          讓我們看看最典型的配置:

          1. <Resource type="javax.sql.DataSource" 
          2.            name="jdbc/TestDB" 
          3.            factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          4.            driverClassName="com.mysql.jdbc.Driver" 
          5.            url="jdbc:mysql://localhost:3306/mysql" 
          6.            username="mysql_user" 
          7.            password="mypassword123" 
          8.            testOnBorrow="true" 
          9.            validationQuery="SELECT 1" 
          10.            /> 

          在這個配置中,java代碼每次調用 Connection con = dataSource.getConnection()時都會執行一次SELECT 1查詢。

           

          這樣保證了在連接提交給應用之前都已經測試過了。但是,對于在短時間內頻繁使用連接的應用,會對性能有嚴重的影響。這有兩個其他的配置選項:

          • testWhileIdle
          • testOnReturn

          當在錯誤的時間對連接做測試,它們也不是真正的很有幫助。

          對于很多應用來說,沒有校驗不是一個真正的困難。一些應用可以繞過校驗通過設置minIdle=0和給minEvictableIdleTimeMillis一個很小的值,所以如果連接空閑了足夠長的時間會讓數據庫會話超時,在此之前連接池將會移除這些空閑太久的連接。

          最好的解決辦法就是測試那些有一段時間沒被測試過的連接。

          1. <Resource type="javax.sql.DataSource" 
          2.             name="jdbc/TestDB" 
          3.             factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          4.             driverClassName="com.mysql.jdbc.Driver" 
          5.             url="jdbc:mysql://localhost:3306/mysql" 
          6.             username="mysql_user" 
          7.             password="mypassword123" 
          8.             testOnBorrow="true" 
          9.             validationQuery="SELECT 1" 
          10.             validationInterval="30000" 
          11.             /> 

          在這個配置中,連接校驗的間隔不會超過30s。這是在性能和連接驗證上的折中。正如前面提到的,如果我們想僥幸驗證所有的連接,我們可以配置連接池中所有空閑連接超時。

           

          1. <Resource type="javax.sql.DataSource" 
          2.             name="jdbc/TestDB" 
          3.             factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          4.             driverClassName="com.mysql.jdbc.Driver" 
          5.             url="jdbc:mysql://localhost:3306/mysql" 
          6.             username="mysql_user" 
          7.             password="mypassword123" 
          8.             timeBetweenEvictionRunsMillis="5000" 
          9.             minEvictableIdleTimeMillis="5000" 
          10.             minIdle="0" 
          11.             /> 

           

          建立數據庫客戶會話

          在一些案例中,當初始化一個新的數據庫會話時需要執行一些任務??赡馨▓绦幸粋€簡單的SQL聲明或者執行一個存儲過程。
          當你創建觸發器時候,這是在數據庫層面上的典型操作。

          1. create or replace trigger logon_alter_session after logon on database 
          2.   begin 
          3.     if sys_context('USERENV', 'SESSION_USER') = 'TEMP' then 
          4.       EXECUTE IMMEDIATE 'alter session ....'; 
          5.     end if; 
          6.   end; 
          7.   / 

          這將影響所有的用戶,在后面這種情況下這是不夠的,當創建一個新的會話的時候我們希望執行一個自定義查詢。

           

          1. <Resource name="jdbc/TestDB" auth="Container" 
          2.             type="javax.sql.DataSource" 
          3.             description="Oracle Datasource" 
          4.             url="jdbc:oracle:thin:@//localhost:1521/orcl" 
          5.             driverClassName="oracle.jdbc.driver.OracleDriver" 
          6.             username="default_user" 
          7.             password="password" 
          8.             maxActive="100" 
          9.             validationQuery="select 1 from dual" 
          10.             validationInterval="30000" 
          11.             testOnBorrow="true" 
          12.             initSQL="ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY MM DD HH24:MI:SS'"/> 

          initSQL會被存在的每一條連接執行。

           

          連接池泄露和長時間運行的查詢

          連接池包含一些診斷操作。jdbc-pool和Common DBCP都能夠檢測和減輕沒有返回連接池中的連接。這里演示是被稱為拋出內存泄露的連接。

          1. Connection con = dataSource.getConnection(); 
          2. Statement st = con.createStatement(); 
          3. st.executeUpdate("insert into id(value) values (1'); //SQLException here 
          4. con.close(); 
          這有5個配置選項用來檢測這些錯誤類型的連接,前三個選項配置在Common DBCP中也有

           

          1. <Resource type="javax.sql.DataSource" 
          2.             name="jdbc/TestDB" 
          3.             factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          4.             driverClassName="com.mysql.jdbc.Driver" 
          5.             url="jdbc:mysql://localhost:3306/mysql" 
          6.             username="mysql_user" 
          7.             password="mypassword123" 
          8.             maxActive="100" 
          9.             timeBetweenEvictionRunsMillis="30000" 
          10.             removeAbandoned="true" 
          11.             removeAbandonedTimeout="60" 
          12.             logAbandoned="true" 
          13.             /> 

           

          • removeAbandoned-如果我們想檢測內存泄露的連接,可以設置為true
          • removeAbandonedTimeout-調用dataSource.getConnection開始到丟棄檢測到泄露連接的時間(seconds)
          • logAbandoned-如果想用log記錄丟棄的連接,可以設置為true。當設置為true時,調用dataSource.getConnection 時會記錄一個堆棧追蹤,并且被打印出來當連接沒有返回的時候。

          但我們想要這種類型的診斷,當然有可以使用的例子。也可以運行批處理作業一次執行一個連接幾分鐘。我們該如何處理這些問題?
          兩個額外的選項已經被加入來支持這些工作

          1. <Resource type="javax.sql.DataSource" 
          2.            name="jdbc/TestDB" 
          3.            factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          4.            driverClassName="com.mysql.jdbc.Driver" 
          5.            url="jdbc:mysql://localhost:3306/mysql" 
          6.            username="mysql_user" 
          7.            password="mypassword123" 
          8.            maxActive="100" 
          9.            timeBetweenEvictionRunsMillis="30000" 
          10.            removeAbandoned="true" 
          11.            removeAbandonedTimeout="60" 
          12.            logAbandoned="true" 
          13.            abandonWhenPercentageFull="50" 
          14.            /> 

           

          • abandonWhenPercentageFull-一條連接必須滿足臨界值 removeAbandonedTimeout和打開連接的數量必須超過這個百分比。


          使用這個屬性可能會在一次錯誤判斷中產生在其他地方已經被認為丟棄的連接。設置這個值為100時意味著連接數除非到了maxActive限制時,是不會被考慮丟棄的。這給連接池增加了一些靈活性,但是不會讓批處理作業使用單獨連接5分鐘。在這種情況,我們想確定當我們檢測到連接仍然被使用時,我們重置超時計時器,因此,連接不會被考慮丟棄。我們通過插入一個攔截器實現。

          1. <Resource type="javax.sql.DataSource" 
          2.             name="jdbc/TestDB" 
          3.             factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          4.             driverClassName="com.mysql.jdbc.Driver" 
          5.             url="jdbc:mysql://localhost:3306/mysql" 
          6.             username="mysql_user" 
          7.             password="mypassword123" 
          8.             maxActive="100" 
          9.             timeBetweenEvictionRunsMillis="30000" 
          10.             removeAbandoned="true" 
          11.             removeAbandonedTimeout="60" 
          12.             logAbandoned="true" 
          13.             abandonWhenPercentageFull="50" 
          14.             jdbcInterceptors="ResetAbandonedTimer" 
          15.             />  

          攔截器在org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer中被指定完全限定名稱,或者在org.apache.tomcat.jdbc.pool.interceptor包中使用短類名
          每次準備語句或者執行一次查詢,連接池中的計時器會被重置放棄計時器。因為如此,在5分鐘的批處理作業中執行多次查詢和更新,都不會超時。

           

          這是你當然想知道的情形,但你不會想去kill或者回收連接,因為你不會知道會對你的系統產生什么影響。

          1. <Resource type="javax.sql.DataSource" 
          2.             name="jdbc/TestDB" 
          3.             factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          4.             driverClassName="com.mysql.jdbc.Driver" 
          5.             url="jdbc:mysql://localhost:3306/mysql" 
          6.             username="mysql_user" 
          7.             password="mypassword123" 
          8.             maxActive="100" 
          9.             timeBetweenEvictionRunsMillis="30000" 
          10.             logAbandoned="true" 
          11.             suspectTimeout="60" 
          12.             jdbcInterceptors="ResetAbandonedTimer" 
          13.             /> 

          suspectTimeout屬性的工作方式與removeAbandonedTimeout 相似,除了不關閉連接,而只是簡單的記錄警告和發布一個JMX通知信息。通過這種方式,你可以在不用改變你系統行為的情況下發現泄漏或者長查詢。

           

          從其它的數據源形成連接池

          到目前為止我們處理連接池連接的獲得是通過java.sql.Driver接口。因此我們使用屬性

          • driverClassName
          • url

          然而,一些連接配置是使用 javax.sql.DataSource 甚至是javax.sql.XADataSource接口,因此我們需要支持這些配置選項。
          使用java相對是很容易的。

          1.     PoolProperties pp = new PoolProperties(); 
          2. pp.setDataSource(myOtherDataSource); 
          3. DataSource ds = new DataSource(pp); 
          4. Connection con = ds.getConnection(); 
          或者

           

          1.     DataSource ds = new DataSource(); 
          2. ds.setDataSource(myOtherDataSource); 
          3. Connection con = ds.getConnection(); 
          我們能夠注入另外的 javax.sql.DataSource或者 javax.sql.XADataSource對象并且用來連接檢索。
          在我們處理XA連接時很方便。

           

          在XML配置中,jdbc-pool會使用org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory類,一個能夠允許配置任何類型的命名資源的簡單類。為了設置Apache Derby XADataSource 我們可以創建了下面的代碼

          1. <Resource factory="org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory"  
          2.             name="jdbc/DerbyXA1" 
          3.             type="org.apache.derby.jdbc.ClientXADataSource" 
          4.             databaseName="sample1" 
          5.             createDatabase="create" 
          6.             serverName="localhost" 
          7.             portNumber="1527" 
          8.             user="sample1" 
          9.             password="password"/> 

          這是一個簡單的通過端口1527連接到網絡上的相鄰實例的XADataSource.

           

          如果你想要從這個數據源形成XA連接池,我們可以在它后面建立這個連接池節點。

          1. <Resource factory="org.apache.tomcat.jdbc.naming.GenericNamingResourcesFactory" 
          2.             name="jdbc/DerbyXA1" 
          3.             type="org.apache.derby.jdbc.ClientXADataSource" 
          4.             databaseName="sample1" 
          5.             createDatabase="create" 
          6.             serverName="localhost" 
          7.             portNumber="1527" 
          8.             user="sample1" 
          9.             password="password"/> 
          10.             <Resource factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          11.             dataSourceJNDI="DerbyXA1"<!--Links to the Derby XADataSource--> 
          12.             name="jdbc/TestDB1" 
          13.             auth="Container" 
          14.             type="javax.sql.XADataSource" 
          15.             testWhileIdle="true" 
          16.             testOnBorrow="true" 
          17.             testOnReturn="false" 
          18.             validationQuery="SELECT 1" 
          19.             validationInterval="30000" 
          20.             timeBetweenEvictionRunsMillis="5000" 
          21.             maxActive="100" 
          22.             minIdle="10" 
          23.             maxIdle="20" 
          24.             maxWait="10000" 
          25.             initialSize="10" 
          26.             removeAbandonedTimeout="60" 
          27.             removeAbandoned="true" 
          28.             logAbandoned="true" 
          29.             minEvictableIdleTimeMillis="30000" 
          30.             jmxEnabled="true" 
          31.             jdbcInterceptors="ConnectionState;StatementFinalizer;SlowQueryReportJmx(threshold=10000)" 
          32.             abandonWhenPercentageFull="75"/> 
          注意 type=javax.sql.XADataSource 是怎樣設置的,這會創建一個org.apache.tomcat.jdbc.pool.XADataSource來代替org.apache.tomcat.jdbc.pool.DataSource。
          這里我們通過dataSourceJNDI=DerbyXA1屬性鏈接這兩個數據源。這兩個數據源都不得不存在同一個命名空間,在我們的例子中,是jdbc命名空間。

           

          目前JNDI通過DataSource.setDataSourceJNDI(...)查找不被支持,只能通過factory對象。

          如果你加入一個

          • javax.sql.DataSource對象-連接池將會調用 javax.sql.DataSource.getConnection()方法
          • javax.sql.DataSource 對象但是在連接池中指定了username/password-連接池將會調用javax.sql.DataSource.getConnection(String username, String password) 方法
          • javax.sql.XADataSource對象-連接池將會調用 javax.sql.XADataSource.getXAConnection()方法
          • javax.sql.XADataSource 對象但是在連接池中指定了 username/password-連接池將會調用 javax.sql.DataSource.getXAConnection(String username, String password)方法

          這是一個有趣的現象當你處理 XADataSources。你可以把返回的對象轉換為java.sql.Connection對象或者javax.sql.XAConnection對象,并且對同一個對象的兩個接口調用方法。

          1.     DataSource ds = new DataSource(); 
          2. ds.setDataSource(myOtherDataSource); 
          3. Connection con = ds.getConnection(); 
          4. if (con instanceof XAConnection) { 
          5.         XAConnection xacon = (XAConnection)con; 
          6.         transactionManager.enlistResource(xacon.getXAResource()); 
          7. Statement st = con.createStatement(); 
          8. ResultSet rs = st.executeQuery(SELECT 1); 

           

          JDBC 攔截器

          JDBC 攔截器創建是為了實現靈活性。javax.sql.PooledConnection 從底層驅動封裝了java.sql.Connection/javax.sql.XAConnection或者數據源本身就是一個攔截器。攔截器以java.lang.reflect.InvocationHandler接口為基礎。攔截器是一個繼承自org.apache.tomcat.pool.jdbc.JdbcInterceptor的類。

          在本文中,我們將介紹如果配置攔截器。在我們下一篇文章,我們將介紹如果實現自定義攔截器和它們的生命周期。

          1. <Resource factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          2.   
          3.             ... 
          4.             jdbcInterceptors="ConnectionState;StatementFinalizer;SlowQueryReportJmx(threshold=10000)" 
          5.   
          6.   /> 

          與下面的相同

           

          1. <Resource factory="org.apache.tomcat.jdbc.pool.DataSourceFactory" 
          2.   
          3.             ... 
          4.            jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState; 
          5.            org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer; 
          6.            org.apache.tomcat.jdbc.pool.interceptor.SlowQueryReportJmx(threshold=10000)" 
          7.   /> 

          攔截器可以使用一個短小的名稱,比如ConnectionState,如果這個攔截器定義在org.apache.tomcat.jdbc.pool.interceptor 包中。

           

          否則,必須使用一個完全限定名稱。

          攔截器定義在以;分割的字符串中。攔截器可以在括號內定義0個或多個參數。參數是以逗號分割的簡單鍵值對。

          連接狀態

          java.sql.Connection接口有如下屬性

          •        autoCommit
          •         readOnly
          •         transactionIsolation
          •         catalog

          這些屬性的默認值可以使用如下的內容為連接池配置

          •         defaultAutoCommit
          •         defaultReadOnly
          •         defaultTransactionIsolation
          •         defaultCatalog

          如果設置了這些屬性,當建立連接到數據庫時配置這個連接。如果沒有配置 ConnectionState攔截器,在建立連接時設置這些屬性會是一次性操作。如果配置了ConnectionState攔截器,每次從連接池取出的連接會將被重置為期望的狀態。

          其中有些方法在執行查詢時會導致往返數據庫。比如,調用 Connection.getTransactionIsolation()會導致驅動查詢當前會話的事務隔離級別。這種往返會導致嚴重的性能問題并影響應用在頻繁的使用連接執行非常短和快的操作的時候。 ConnectionState 攔截器可以緩存這些操作的值并調用方法查詢它們從而避免往返數據庫。

          Statement Finalizer

          java代碼在使用java.sql對象后需要清除和釋放使用過的資源。

          一個清理代碼示例

          1.            Connection con = null
          2. Statement st = null
          3. ResultSet rs = null
          4. try { 
          5.             con = ds.getConnection(); 
          6.             ... 
          7.  
          8. } finally { 
          9.             if (rs!=null) try  { rs.close(); } catch (Exception ignore){} 
          10.             if (st!=null) try  { st.close(); } catch (Exception ignore){} 
          11.             if (con!=null) try { con.close();} catch (Exception ignore){} 
          一些應用并不總是使用這種方式。我們以前展示了如何配置連接池去診斷和警告當連接沒有正確關閉的情況。

           

          當一個連接返回連接池的時候,StatementFinalizer攔截器確保 java.sql.Statement和它的子類正確關閉。

          獲得真正的JDBC連接

          使用javax.sql.PooledConnection工具返回代理連接,因此取出連接十分直接,不需要轉換為特殊的類。

          同樣適用于你配置了處理javax.sql.XAConnection的連接池。

          另一個有趣的取出底層連接的方法是

          1. Connection con = ds.getConnection(); 
          2. ction underlyingconnection = con.createStatement().getConnection(); 
          這是因為jdbc-pool默認的是沒有代理聲明。這當然有一個攔截器用來阻止這個用例。
          posted on 2014-07-29 10:03 張金鵬 閱讀(646) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
          主站蜘蛛池模板: 静乐县| 宁安市| 湟中县| 靖宇县| 香港| 定西市| 靖安县| 巫溪县| 大化| 东城区| 洮南市| 望奎县| 南安市| 睢宁县| 江源县| 九台市| 修水县| 闵行区| 游戏| 江华| 凉城县| 绥阳县| 上高县| 维西| 安岳县| 扶沟县| 运城市| 巴南区| 图片| 潍坊市| 黎平县| 广宗县| 仁化县| 庆阳市| 濮阳市| 宣恩县| 确山县| 遂溪县| 黔江区| 潜江市| 获嘉县|