日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

(十二)C3P0连接池使用教程

發布時間:2023/12/3 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 (十二)C3P0连接池使用教程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一般我們在項目中操作數據庫時,都是每次需要操作數據庫就建立一個連接,操作完成后釋放連接。因為jdbc沒有保持連接的能力,一旦超過一定時間沒有使用(大約幾百毫秒),連接就會被自動釋放掉。而每次新建連接都需要140毫秒左右的時間,所以耗費時間比較多。若使用C3P0連接池來池化連接,隨時取用,則平均每次取用只需要10-20毫秒。這在高并發隨機訪問數據庫的時候對效率的提升有很大幫助。

??? C3P0連接池會根據你的配置來初始化N個數據庫連接,空閑T時間后連接過期又會自動新建K個連接使得連接池總有空閑的數據庫連接等待被取用。我們只需通過dataSourse.getConnection()即可從線程池中取用一個已經連接好的空閑連接,執行數據庫操作。然后“斷開”(放回)這個連接,把這個連接的使用權放回連接池。真正的數據庫連接的創建與釋放是由C3P0在后臺自動完成的,我們花的只是取用與釋放占用權的時間。全程耗時10+毫秒,比原來提高了幾十倍。

??? 下面介紹一種C3P0的三層式使用。與一般的C3P0使用方式不同,三層式把數據庫操作分為了三部分:C3P0操作類C3P0Utils、封裝了一次數據庫操作的VO對象DBUtils_BO、數據庫操作類DBUtils。下面一一講解:

?一:C3P0Utils:負責從連接池獲取一個連接、放回一個連接。

?這里主要是C3P0連接池的使用。步驟如下:

??? 1:下載C3P0工具包:? https://sourceforge.net/projects/c3p0/files/latest/download?source=files

??? 解壓出來后得到3個jar包,導入你的項目中。

??? 2:對C3P0連接池進行配置。

??? 主要包括:初始化連接池時建立多少個連接、連接池最少多少個連接最多容納多少連接、每個連接的生存時間、連接池能同時允許多少個操作進行,以及對具體數據庫連接的配置:數據庫的驅動、數據庫的URL、數據庫登錄名、數據庫密碼、對這個數據庫的連接池的細化配置(比如初始化時建立多少連接,最多最少連接數等等)。一個數據庫的連接池配置用一個<named-config?name="標識"> </name-config>節點來定義。在C3P0Utils中創建連接池時把? “標識”? 作為連接池的構造函數的參數傳入,則C3P0在配置文件中找到同名節點,按照這個節點的配置來創建相應配置的連接池。配置步驟如下:

在src目錄下新建一個名叫? c3p0-config.xml? 的文件,注意,必須是這個文件名。

<?xml version="1.0" encoding="UTF-8"?> <c3p0-config><!--默認配置--><default-config> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> </default-config> <!--配置連接池mysql--><named-config name="mysql"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/CoupleSpace</property> <property name="user">root</property> <property name="password">root</property> <property name="initialPoolSize">10</property> <property name="maxIdleTime">30</property> <property name="maxPoolSize">100</property> <property name="minPoolSize">10</property> <property name="maxStatements">200</property> </named-config> <!--配置連接池2-->......<!--配置連接池3-->......<!--配置連接池4-->...... </c3p0-config>

更細致化的有以下配置:

<!--acquireIncrement:鏈接用完了自動增量3個。 --><property name="acquireIncrement">3</property><!--acquireRetryAttempts:鏈接失敗后重新試30次。--><property name="acquireRetryAttempts">30</property><!--acquireRetryDelay;兩次連接中間隔1000毫秒。 --><property name="acquireRetryDelay">1000</property><!--autoCommitOnClose:連接關閉時默認將所有未提交的操作回滾。 --><property name="autoCommitOnClose">false</property><!--automaticTestTable:c3p0測試表,沒什么用。--><property name="automaticTestTable">Test</property><!--breakAfterAcquireFailure:出錯時不把正在提交的數據拋棄。--><property name="breakAfterAcquireFailure">false</property><!--checkoutTimeout:100毫秒后如果sql數據沒有執行完將會報錯,如果設置成0,那么將會無限的等待。 --> <property name="checkoutTimeout">100</property><!--connectionTesterClassName:通過實現ConnectionTester或QueryConnectionTester的類來測試連接。類名需制定全路徑。Default: com.mchange.v2.c3p0.impl.DefaultConnectionTester--><property name="connectionTesterClassName"></property><!--factoryClassLocation:指定c3p0 libraries的路徑,如果(通常都是這樣)在本地即可獲得那么無需設置,默認null即可。--><property name="factoryClassLocation">null</property><!--forceIgnoreUnresolvedTransactions:作者強烈建議不使用的一個屬性。--> <property name="forceIgnoreUnresolvedTransactions">false</property><!--idleConnectionTestPeriod:每60秒檢查所有連接池中的空閑連接。--> <property name="idleConnectionTestPeriod">60</property><!--initialPoolSize:初始化時獲取三個連接,取值應在minPoolSize與maxPoolSize之間。 --> <property name="initialPoolSize">3</property><!--maxIdleTime:最大空閑時間,60秒內未使用則連接被丟棄。若為0則永不丟棄。--><property name="maxIdleTime">60</property><!--maxPoolSize:連接池中保留的最大連接數。 --><property name="maxPoolSize">15</property><!--maxStatements:最大鏈接數。--><property name="maxStatements">100</property><!--maxStatementsPerConnection:定義了連接池內單個連接所擁有的最大緩存statements數。Default: 0 --><property name="maxStatementsPerConnection"></property><!--numHelperThreads:異步操作,提升性能通過多線程實現多個操作同時被執行。Default: 3--> <property name="numHelperThreads">3</property><!--overrideDefaultUser:當用戶調用getConnection()時使root用戶成為去獲取連接的用戶。主要用于連接池連接非c3p0的數據源時。Default: null--> <property name="overrideDefaultUser">root</property><!--overrideDefaultPassword:與overrideDefaultUser參數對應使用的一個參數。Default: null--><property name="overrideDefaultPassword">password</property><!--password:密碼。Default: null--> <property name="password"></property><!--preferredTestQuery:定義所有連接測試都執行的測試語句。在使用連接測試的情況下這個一顯著提高測試速度。注意: 測試的表必須在初始數據源的時候就存在。Default: null--><property name="preferredTestQuery">select id from test where id=1</property><!--propertyCycle:用戶修改系統配置參數執行前最多等待300秒。Default: 300 --> <property name="propertyCycle">300</property><!--testConnectionOnCheckout:因性能消耗大請只在需要的時候使用它。Default: false --><property name="testConnectionOnCheckout">false</property><!--testConnectionOnCheckin:如果設為true那么在取得連接的同時將校驗連接的有效性。Default: false --><property name="testConnectionOnCheckin">true</property><!--user:用戶名。Default: null--><property name="user">root</property><!--usesTraditionalReflectiveProxies:動態反射代理。Default: false--><property name="usesTraditionalReflectiveProxies">false</property>

(另:有人試過用properties文件來配置C3P0,通過setProperties(properties)方法并不能成功設置連接池的屬性,而需要一條條屬性去設置setXXX(properties.get(XX))才能成功設置。我的理解是:連接池本身有一個屬性叫做properties,然后調用setProperties()方法只是把配置文件賦值給了連接池的properties屬性而已,而不是讀取這個配置文件并把這個配置文件中的key-value對提取出來并set給連接池的相應屬性。所以,還需要手動加載這個文件,并且逐條屬性去設置給連接池。而我們這里用xml文件去配置的話,C3P0創建連接池時是自動根據這個文件的配置去創建的,所以配置生效。)

??? 3:創建C3P0Utils類,定義獲取connection、釋放connection的方法

public class C3p0Utils {static org.apache.log4j.Logger logger=org.apache.log4j.Logger.getLogger(C3p0Utils.class.getName());//通過標識名來創建相應連接池static ComboPooledDataSource dataSource=new ComboPooledDataSource("mysql");//從連接池中取用一個連接public static Connection getConnection(){try {return dataSource.getConnection();} catch (Exception e) {logger.error("Exception in C3p0Utils!", e);throw new MyError("數據庫連接出錯!", e); }} //釋放連接回連接池public static void close(Connection conn,PreparedStatement pst,ResultSet rs){ if(rs!=null){ try { rs.close(); } catch (SQLException e) { logger.error("Exception in C3p0Utils!", e);throw new MyError("數據庫連接關閉出錯!", e); } } if(pst!=null){ try { pst.close(); } catch (SQLException e) { logger.error("Exception in C3p0Utils!", e);throw new MyError("數據庫連接關閉出錯!", e); } } if(conn!=null){ try { conn.close(); } catch (SQLException e) { logger.error("Exception in C3p0Utils!", e);throw new MyError("數據庫連接關閉出錯!", e); } } } }

??二:創建DBUtils_BO類來封裝一次數據庫操作

??? BO類中主要封裝了一個數據庫連接、一個Statement/PreStatement(推薦,更安全)、一個結果集。這樣,在DAO層的一次數據庫操作就可封裝在這個bo對象里,直接把這個對象傳給數據庫操作類執行數據庫操作即可。操作完成后的結果集也封裝在了這個bo對象里,在需要提取結果的地方通過這個bo對象的rs字段進行結果提取即可。

public class DBUtil_BO { public Connection conn = null;public PreparedStatement st = null;public ResultSet rs = null;public DBUtil_BO() {super();} }

???三:創建DBUtils數據庫操作類進行具體的數據庫操作

?? 數據庫操作類主要負責執行數據庫操作封裝類bo對象的操作以及釋放連接回連接池,并把結果封裝回bo對象。

public class DBUtils {static org.apache.log4j.Logger logger=org.apache.log4j.Logger.getLogger(DBUtils.class.getName());private static void realseSource( Connection _conn, PreparedStatement _st,ResultSet _rs){ C3p0Utils.close(_conn,_st,_rs);}public static void realseSource(DBUtil_BO _vo){ if(_vo!=null){realseSource(_vo.conn, _vo.st, _vo.rs);} }//注意:查詢操作完成后,因為還需提取結果集中信息,所以仍保持連接,在結果集使用完后才通過DBUtils.realseSource()手動釋放連接public static void executeQuery(DBUtil_BO vo){ try{vo.rs = vo.st.executeQuery();}catch (SQLException e){ realseSource(vo);String uuid=Uuid.create().toString();logger.error("UUID:"+uuid+", SQL語法有誤: ",e);throw new MyException("err.user.dao.jdbc",e,uuid);} }//而update操作完成后就可以直接釋放連接了,所以在方法末尾直接調用了realseSourse()public static void executeUpdate(DBUtil_BO vo){Connection conn = vo.conn;PreparedStatement st = vo.st;try {st.executeUpdate();} catch (SQLException e) {realseSource(conn, st, null); String uuid=Uuid.create().toString();logger.error("UUID:"+uuid+", SQL語法有誤: ",e);throw new MyException("err.user.dao.jdbc",e,uuid);}realseSource(conn, st,null ); } }

?四:在項目中使用連接池

??? 主要分5步:

??? 1:創建連接池datasourse、bo、utils對象

??? 2:bo對象的連接是在連接池獲取的,所以bo.conn=C3P0Utils.getConnection();

??? 3:定義數據庫操作語句sql,并用bo對象的preparestatement預處理

??? 4:把封裝了數據庫操作的bo對象傳給utils對象執行數據庫操作

??? 5:bo對象釋放連接,以便下一次獲取連接。(查詢操作的需要顯示釋放)

dbBo.conn=C3p0Utils.getConnection();//取用一個連接 String sql = "select * from users where username=? and password=?"; dbBo.st=dbBo.conn.prepareStatement(sql);//預處理sql語句 dbBo.st.setString(1, name); dbBo.st.setString(2, pass); //此時dbBo對象已經封裝了一個數據庫連接以及要執行的操作 dbUtils.executeQuery(dbBo);//通過數據庫操作類來執行這個操作封裝類,結果封裝回這個操作封裝類//從dbBo類提取操作結果 if (dbBo.rs.next()) {uid =dbBo.rs.getInt("userid");} //結果集遍歷完了,手動釋放連接回連接池 dbUtils.realseSource(dbBo);

?

總結

以上是生活随笔為你收集整理的(十二)C3P0连接池使用教程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。