JDBC連接數據庫(二)——連接池


參考博客:http://www.cnblogs.com/xdp-gacl/p/4002804.html

 

一、 應用程序直接建立數據庫連接模型

應用程序直接每次訪問數據庫時,都建立創建一個數據庫的鏈接,這樣每次建立這樣的連接都需要耗費的資源,當同時有很多用戶在使用應用程序時,可能會導致應用程序崩潰。

  圖為應用程序直接建立數據庫連接模型

二、使用數據庫連接池優化模型

數據庫連接池的基本思路是,平時建立適量的數據庫的連接,放在一個集合中,當有用戶需要建立數據庫連接的時候,直接到集合中取出一個數據庫連接對象(Connection),這樣不用再需要重新創建,這樣會節省大量的資源,當用戶不需要在對數據庫進行訪問了,那么就將數據庫連接對象(Connection)重新放回到集合中,以便方便下次使用。          

 數據庫連接池優化模型圖

 

1、關於連接池中的連接數量的一些規定:

(1)最小連接數:是連接池一直保持的數據庫連接,所以如果應用程序對數據庫連接的使用量不大,將會有大量的數據庫連接資源被浪費(適量).

(2)最大連接數:是連接池能申請的最大連接數,如果數據庫連接請求超過次數,后面的數據庫連接請求將被加入到等待隊列中,這會影響以后的數據庫操作。通常在使用完起始集合中的連接后,會再重新創建一些數據庫連接對象,用來滿足用戶需求,但是這種新建並不是無限制的。

(3)當使用完的連接對象需要重新放回到集合中以備使用,但是超過最小連接數的連接在使用完不會馬上被釋放,他將被放到連接池中等待重復使用或是超時后最終被釋放。

 

2、編寫數據庫連接池

簡單思路為:創建一個類繼承DataSource接口,在類中實現靜態的加載出配置文檔db.properties文檔,並創建最小連接量的數據庫連接對象(Connection),添加到Linkedlist(選擇Linkedlist集合原因是便於增刪)集合中。重寫getConnection()函數,在getConnection()函數中實現數據庫連接對象的獲取。

db.properties文檔

1 driver=com.mysql.jdbc.Driver
2 url=jdbc:mysql://127.0.0.1:3306/imooc?useUnicode=true&characterEncoding=utf-8
3 username=root
4 password=tiger
5  
6 jdbcConnectionInitSize=10

     創建數據庫連接池:

  1 package JDBC;
  2 
  3 import java.io.IOException;
  4 import java.io.InputStream;
  5 import java.io.PrintWriter;
  6 import java.lang.reflect.InvocationHandler;
  7 import java.lang.reflect.Method;
  8 import java.lang.reflect.Proxy;
  9 import java.sql.Connection;
 10 import java.sql.DriverManager;
 11 import java.sql.SQLException;
 12 import java.sql.SQLFeatureNotSupportedException;
 13 import java.util.LinkedList;
 14 import java.util.Properties;
 15 import java.util.logging.Logger;
 16 
 17 import javax.sql.DataSource;
 18 
 19 public class JdbcConnectionsPool implements DataSource {
 20 
 21     /*
 22      * 使用靜態塊代碼,初始化連接池,創建連接池的中最小鏈接數量連接,
 23      * 創建linkedlist集合,將這些連接放入集合中
 24      */
 25     //創建linkedlist集合
 26     private static LinkedList<Connection> linkedlist1=new LinkedList<Connection>();
 27     private static String driver;//
 28     private static String url;//
 29     private static String username;//數據庫登陸名
 30     private static String password;//數據庫的登陸密碼
 31     private static int jdbcConnectionInitSize;//最小連接數量
 32     private static int max=1; //當前最大連接數量=max*jdbcConnectionInitSize
 33     static{
 34         //通過反射機制獲取訪問db.properties文件
 35         InputStream is=JdbcConnectionsPool.class.getResourceAsStream("/db.properties");
 36         Properties prop=new Properties();
 37         try {
 38             //加載db.properties文件
 39             prop.load(is);
 40             //獲取db.properties文件中的數據庫連接信息
 41             driver=prop.getProperty("driver");
 42             url=prop.getProperty("url");
 43             username=prop.getProperty("username");
 44             password=prop.getProperty("password");
 45             jdbcConnectionInitSize=Integer.parseInt(prop.getProperty("jdbcConnectionInitSize"));
 46             
 47             Class.forName("com.mysql.jdbc.Driver");
 48             
 49             //創建最小連接數個數據庫連接對象以備使用
 50             for(int i=0;i<jdbcConnectionInitSize;i++){
 51                 Connection conn=DriverManager.getConnection(url, username, password);
 52                  System.out.println("獲取到了鏈接" + conn);
 53                 //將創建好的數據庫連接對象添加到Linkedlist集合中
 54                 linkedlist1.add(conn);
 55             }
 56             
 57             
 58         } catch (IOException e) {
 59             // TODO Auto-generated catch block
 60             e.printStackTrace();
 61         } catch (SQLException e) {
 62             // TODO Auto-generated catch block
 63             e.printStackTrace();
 64         } catch (ClassNotFoundException e) {
 65             // TODO Auto-generated catch block
 66             e.printStackTrace();
 67         }
 68         
 69     }
 70     
 71     
 72     @Override
 73     public PrintWriter getLogWriter() throws SQLException {
 74         // TODO Auto-generated method stub
 75         return null;
 76     }
 77 
 78     @Override
 79     public void setLogWriter(PrintWriter out) throws SQLException {
 80         // TODO Auto-generated method stub
 81 
 82     }
 83 
 84     @Override
 85     public void setLoginTimeout(int seconds) throws SQLException {
 86         // TODO Auto-generated method stub
 87 
 88     }
 89 
 90     @Override
 91     public int getLoginTimeout() throws SQLException {
 92         // TODO Auto-generated method stub
 93         return 0;
 94     }
 95 
 96     @Override
 97     public Logger getParentLogger() throws SQLFeatureNotSupportedException {
 98         // TODO Auto-generated method stub
 99         return null;
100     }
101 
102     @Override
103     public <T> T unwrap(Class<T> iface) throws SQLException {
104         // TODO Auto-generated method stub
105         return null;
106     }
107 
108     @Override
109     public boolean isWrapperFor(Class<?> iface) throws SQLException {
110         // TODO Auto-generated method stub
111         return false;
112     }
113 
114     /*
115      * 實現數據庫連接的獲取和新創建
116      */
117     @Override
118     public Connection getConnection() throws SQLException {
119          //如果集合中沒有數據庫連接對象了,且創建的數據庫連接對象沒有達到最大連接數量,可以再創建一組數據庫連接對象以備使用
120          if(linkedlist1.size()==0&&max<=5){
121              try {
122                 Class.forName("com.mysql.jdbc.Driver");
123             } catch (ClassNotFoundException e) {
124                 // TODO Auto-generated catch block
125                 e.printStackTrace();
126             }
127              for(int i=0;i<jdbcConnectionInitSize;i++){
128                Connection conn=DriverManager.getConnection(url, username, password);
129                System.out.println("獲取到了鏈接" + conn);
130                //將創建好的數據庫連接對象添加到Linkedlist集合中
131                linkedlist1.add(conn);
132                 }
133              max++;
134             }
135         if(linkedlist1.size()>0){
136             //從linkedlist集合中取出一個數據庫鏈接對象Connection使用
137             Connection conn1=linkedlist1.removeFirst();
138             System.out.println("linkedlist1數據庫連接池大小是" + linkedlist1.size());
139             /*返回一個Connection對象,並且設置Connection對象方法調用的限制,
140             *當調用connection類對象的close()方法時會將Connection對象重新收集放入linkedlist集合中。
141             */
142             return (Connection) Proxy.newProxyInstance(conn1.getClass().getClassLoader(),//這里換成JdbcConnectionsPool.class.getClassLoader();也行
143                  conn1.getClass().getInterfaces(), new InvocationHandler() {
144                                     
145                     @Override
146                     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
147                         if(!method.getName().equalsIgnoreCase("close")){
148                             return method.invoke(conn1, args);
149                         }else{
150                             linkedlist1.add(conn1);
151                             System.out.println(conn1+"對象被釋放,重新放回linkedlist集合中!");
152                             System.out.println("此時Linkedlist集合中有"+linkedlist1.size()+"個數據庫連接對象!");
153                             return null;
154                             }                    
155                         }
156                    });
157         }else{
158             System.out.println("連接數據庫失敗!");
159         }
160         return null;
161     }
162 
163     @Override
164     public Connection getConnection(String username, String password) throws SQLException {
165 
166         return null;
167     }
168 
169 }

進一步封裝一些相關數據庫的類的方法

 1 package JDBC;
 2 
 3 import java.sql.Connection;
 4 import java.sql.ResultSet;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 
 8 public class JdbcConnectionPoolTest {
 9         
10         /**
11         * @Field: pool
12         *          數據庫連接池
13         */ 
14         private static JdbcConnectionsPool pool = new JdbcConnectionsPool();
15         
16         /**
17         * @Method: getConnection
18         * @Description: 從數據庫連接池中獲取數據庫連接對象
19         * @return Connection數據庫連接對象
20         * @throws SQLException
21         */ 
22         public static Connection getConnection() throws SQLException{
23             return pool.getConnection();
24         }
25         
26         /**
27         * @Method: release
28         * @Description: 釋放資源,
29         * 釋放的資源包括Connection數據庫連接對象,負責執行SQL命令的Statement對象,存儲查詢結果的ResultSet對象
30         * @param conn
31         * @param st
32         * @param rs
33         */ 
34         public static void release(Connection conn,Statement st,ResultSet rs){
35             if(rs!=null){
36                 try{
37                     //關閉存儲查詢結果的ResultSet對象
38                     rs.close();
39                 }catch (Exception e) {
40                     e.printStackTrace();
41                 }
42                 rs = null;
43             }
44             if(st!=null){
45                 try{
46                     //關閉負責執行SQL命令的Statement對象
47                     st.close();
48                 }catch (Exception e) {
49                     e.printStackTrace();
50                 }
51             }
52             
53             if(conn!=null){
54                 try{
55                     //關閉Connection數據庫連接對象
56                     conn.close();
57                 }catch (Exception e) {
58                     e.printStackTrace();
59                 }
60             }
61         }
62     
63 }

調試代碼:

 1 package JDBC;
 2 
 3 import java.sql.Blob;
 4 import java.sql.CallableStatement;
 5 import java.sql.Connection;
 6 import java.sql.ResultSet;
 7 import java.sql.SQLException;
 8 import java.sql.Types;
 9 
10 public class TestJdbcPool {
11 
12     public static void main(String[] args) throws SQLException {
13         //實例化封裝了有關數據庫類方法類的對象
14         JdbcConnectionPoolTest jcpt=new JdbcConnectionPoolTest();
15         //獲得數據庫連接對象
16         Connection conn=jcpt.getConnection();
17         //下面代碼是存儲過程的調用
18         String s="call SP_select_nofilter6(?,?,?) ";
19         CallableStatement cst=conn.prepareCall(s);
20         cst.setInt(2, 2);
21         cst.registerOutParameter(1, Types.VARCHAR);
22         cst.registerOutParameter(3, Types.BLOB);
23         ResultSet rs=cst.executeQuery();
24         String name=cst.getString(1);
25         Blob b=cst.getBlob(3);
26         
27         System.out.println("name:"+name+" Blob:"+b);
28         //關閉所有的數據庫資源
29         jcpt.release(conn, cst, rs);
30     }
31 }

運行結果:

 1 獲取到了鏈接com.mysql.jdbc.Connection@5f184fc6
 2 獲取到了鏈接com.mysql.jdbc.Connection@723279cf
 3 獲取到了鏈接com.mysql.jdbc.Connection@4e50df2e
 4 獲取到了鏈接com.mysql.jdbc.Connection@7cc355be
 5 獲取到了鏈接com.mysql.jdbc.Connection@52cc8049
 6 獲取到了鏈接com.mysql.jdbc.Connection@7530d0a
 7 獲取到了鏈接com.mysql.jdbc.Connection@4fca772d
 8 獲取到了鏈接com.mysql.jdbc.Connection@7cd84586
 9 獲取到了鏈接com.mysql.jdbc.Connection@70177ecd
10 獲取到了鏈接com.mysql.jdbc.Connection@cc34f4d
11 linkedlist1數據庫連接池大小是9
12 name:xiao Blob:com.mysql.jdbc.Blob@5197848c
13 com.mysql.jdbc.Connection@5f184fc6對象被釋放,重新放回linkedlist集合中!
14 此時Linkedlist集合中有10個數據庫連接對象!

標紅的代碼是比較重要的代碼段~,其中Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h),返回一個指定接口的代理類實例,該接口可以將方法調用指派到指定的調用處理程序,loader參數定義代理類的類加載器,interfaces - 代理類要實現的接口列表,h - 指派方法調用的調用處理程序 。

 

三、兩個開源的數據庫連接池

在使用了數據庫連接池之后,在項目的實際開發中就不需要編寫連接數據庫的代碼了,直接從數據源獲得數據庫的連接。

1、dbcp連接

(1)導入相關jar包

commons-dbcp2-2.1.1.jar

commons-pool2-2.4.2.jar

commoms-logging-1.2.jar

(2)在項目根目錄增加配置文件dbcp.properties

 1 #連接設置
 2 driverClassName=com.mysql.jdbc.Driver
 3 url=jdbc:mysql://localhost:3306/jdbcstudy
 4 username=root
 5 password=XDP
 6 
 7 #<!-- 初始化連接 -->
 8 initialSize=10
 9 
10 #最大連接數量
11 maxActive=50
12 
13 #<!-- 最大空閑連接 -->
14 maxIdle=20
15 
16 #<!-- 最小空閑連接 -->
17 minIdle=5
18 
19 #<!-- 超時等待時間以毫秒為單位 6000毫秒/1000等於60秒 -->
20 maxWait=60000
21 
22 
23 #JDBC驅動建立連接時附帶的連接屬性屬性的格式必須為這樣:[屬性名=property;] 
24 #注意:"user" 與 "password" 兩個屬性會被明確地傳遞,因此這里不需要包含他們。
25 connectionProperties=useUnicode=true;characterEncoding=UTF8
26 
27 #指定由連接池所創建的連接的自動提交(auto-commit)狀態。
28 defaultAutoCommit=true
29 
30 #driver default 指定由連接池所創建的連接的只讀(read-only)狀態。
31 #如果沒有設置該值,則“setReadOnly”方法將不被調用。(某些驅動並不支持只讀模式,如:Informix)
32 defaultReadOnly=
33 
34 #driver default 指定由連接池所創建的連接的事務級別(TransactionIsolation)。
35 #可用值為下列之一:(詳情可見javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
36 defaultTransactionIsolation=READ_UNCOMMITTED

(3)程序實現dbcp連接

代碼演示:

數據庫對象的代理類(封裝Connection類的一些方法)

 1 package DBCP;
 2 
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.sql.Connection;
 6 import java.sql.ResultSet;
 7 import java.sql.SQLException;
 8 import java.sql.Statement;
 9 import java.util.Properties;
10 
11 import javax.sql.DataSource;
12 
13 import org.apache.commons.dbcp.BasicDataSourceFactory;
14 
15 public class DBCPUtil {
16     private static DataSource ds;
17     private static final String configFile="/dbcp.properties";
18     
19     public DBCPUtil(){
20         //實例化properties對象用於加載配置文件
21         Properties prop=new Properties();
22         InputStream is=DBCPUtil.class.getResourceAsStream(configFile);
23         try {
24             prop.load(is);
25             ds=BasicDataSourceFactory.createDataSource(prop);
26         } catch (IOException e) {
27             // TODO Auto-generated catch block
28             e.printStackTrace();
29         } catch (Exception e) {
30             // TODO Auto-generated catch block
31             e.printStackTrace();
32         }    
33     }
34     /*
35      * 獲取數據庫連接對象
36      */
37     public Connection getConn(){
38         Connection conn=null;
39         if(ds!=null){
40             try {
41                 conn=ds.getConnection();
42                 conn.setAutoCommit(false);//設置禁止操作自動提交的情況 43             } catch (SQLException e) {
44                 // TODO Auto-generated catch block
45                 e.printStackTrace();
46             }
47             return conn;
48         }
49         return conn;
50     }
51     /*
52      * 封裝數據庫相關資源的關閉工作
53      */
54     public void close(ResultSet rs,Statement st,Connection conn) throws SQLException{
55         if(rs!=null){
56                 rs.close();        
57         }
58         if(st!=null){
59                 st.close();
60         }
61         if(conn!=null){
62             conn.close();
63         }
64     }    
65 }

代碼調用:

 1 package DBCP;
 2 
 3 import java.sql.Blob;
 4 import java.sql.CallableStatement;
 5 import java.sql.Connection;
 6 import java.sql.ResultSet;
 7 import java.sql.SQLException;
 8 import java.sql.Types;
 9 
10 public class DbcpTest {
11 
12     public static void main(String[] args) throws SQLException {
13                 //實例化數據庫連接的代理類
14                 DBCPUtil dbcpUtil=new DBCPUtil();
15                 //獲得數據庫連接對象
16                 Connection conn=dbcpUtil.getConn();
17                 //下面代碼是存儲過程的調用
18                 String s="call SP_select_nofilter6(?,?,?) ";
19                 CallableStatement cst=conn.prepareCall(s);
20                 cst.setInt(2, 2);
21                 cst.registerOutParameter(1, Types.VARCHAR);
22                 cst.registerOutParameter(3, Types.BLOB);
23                 ResultSet rs=cst.executeQuery();
24                 String name=cst.getString(1);
25                 Blob b=cst.getBlob(3);
26                 
27                 System.out.println("name:"+name+" Blob:"+b);
28                 //關閉資源
29                 dbcpUtil.close(rs, cst, conn);
30     }
31 
32 }

運行結果:

name:xiao Blob:com.mysql.jdbc.Blob@30946e09

2、c3p0連接池

c3p0是一個開源的JDBC連接池,它實現了數據源和JNDI綁定支持JDBC3和JDBC2的標准擴展

(1)導入相關的jar包

cc3p0-0.9.2-pre4.jar

mchange-commons-java-0.2.2.jar

如果是oracle數據庫還需要添加c3p0-oracle-thin-extras-0.9.2-pre1.jar

(2)在項目根目錄下增加配置文件

1)c3p0.properties

 1 ##配置除user,password,minpoolsize,maxpoolsize的參數
 2 ##[注意] 整數值不能有空格
 3 #連接設置
 4 driverClassName=com.mysql.jdbc.Driver
 5 url=jdbc:mysql://127.0.0.1:3306/imooc?useUnicode=true&amp;characterEncoding=utf-8
 6 username=root
 7 password=tiger
 8 
 9 #初始化時獲取三個連接,取值應在minPoolSize與maxPoolSize之間。Default: 3 
10 c3p0.initialPoolSize=10
11 
12 #當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數。Default: 3
13 c3p0.acquireIncrement=3
14 
15 #最大空閑時間,60秒內未使用則連接被丟棄。若為0則永不丟棄。Default: 0
16 #maxIdleTime應該小於MySQL的wait_timeout的值
17 c3p0.maxIdleTime=600
18 
19 #定義在從數據庫獲取新連接失敗后重復嘗試的次數。Default: 30 
20 c3p0.acquireRetryAttempts=5
21 
22 #兩次連接中間隔時間,單位毫秒。Default: 1000 
23 c3p0.acquireRetryDelay=1000
24 
25 #連接關閉時默認將所有未提交的操作回滾。Default: false 
26 c3p0.autoCommitOnClose=false
27 
28 #c3p0將建一張名為Test的空表,並使用其自帶的查詢語句進行測試。如果定義了這個參數那么 
29 #屬性preferredTestQuery將被忽略。你不能在這張Test表上進行任何操作,它將只供c3p0測試 
30 #使用。Default: null
31 #c3p0.automaticTestTable=
32 
33 #獲取連接失敗將會引起所有等待連接池來獲取連接的線程拋出異常。但是數據源仍有效 
34 #保留,並在下次調用getConnection()的時候繼續嘗試獲取連接。如果設為true,那么在嘗試 
35 #獲取連接失敗后該數據源將申明已斷開並永久關閉。Default: false
36 #c3p0.breakAfterAcquireFailure=false
37 
38 #當連接池用完時客戶端調用getConnection()后等待獲取新連接的時間,超時后將拋出 
39 #SQLException,如設為0則無限期等待。單位毫秒。Default: 0
40 c3p0.checkoutTimeout=10000
41 
42 #每60秒檢查所有連接池中的空閑連接。Default: 0
43 c3p0.idleConnectionTestPeriod=600
44 
45 #JDBC的標准參數,用以控制數據源內加載的PreparedStatements數量。但由於預緩存的statements 
46 #屬於單個connection而不是整個連接池。所以設置這個參數需要考慮到多方面的因素。 
47 #如果maxStatements與maxStatementsPerConnection均為0,則緩存被關閉。Default: 0
48 c3p0.maxStatements=100
49 
50 #maxStatementsPerConnection定義了連接池內單個連接所擁有的最大緩存statements數。Default: 0
51 c3p0.maxStatementsPerConnection=0
52 
53 #c3p0是異步操作的,緩慢的JDBC操作通過幫助進程完成。擴展這些操作可以有效的提升性能 
54 #通過多線程實現多個操作同時被執行。Default: 3
55 c3p0.numHelperThreads=3

2)c3p0-config.xml文檔

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!--
 3 c3p0-config.xml必須位於類路徑下面
 4 private static ComboPooledDataSource ds;
 5 static{
 6     try {
 7         ds = new ComboPooledDataSource("MySQL");
 8     } catch (Exception e) {
 9         throw new ExceptionInInitializerError(e);
10     }
11 }
12 -->
13 
14 <c3p0-config>
15     <!--
16     C3P0的缺省(默認)配置,
17     如果在代碼中“ComboPooledDataSource ds = new ComboPooledDataSource();”這樣寫就表示使用的是C3P0的缺省(默認)配置信息來創建數據源
18     -->
19     <default-config>
20         <property name="driverClass">com.mysql.jdbc.Driver</property>
21         <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/imooc?useUnicode=true&amp;characterEncoding=utf-8</property>
22         <property name="user">root</property>
23         <property name="password">tiger</property>
24         
25         <property name="acquireIncrement">5</property>
26         <property name="initialPoolSize">10</property>
27         <property name="minPoolSize">5</property>
28         <property name="maxPoolSize">20</property>
29     </default-config>
30 
31     <!--
32     C3P0的命名配置,
33     如果在代碼中“ComboPooledDataSource ds = new ComboPooledDataSource("MySQL");”這樣寫就表示使用的是name是MySQL的配置信息來創建數據源
34     -->
35     <named-config name="MySQL">
36         <property name="driverClass">com.mysql.jdbc.Driver</property>
37         <property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/imooc?useUnicode=true&amp;characterEncoding=utf-8</property>
38         <property name="user">root</property>
39         <property name="password">tiger</property>
40         
41         <property name="acquireIncrement">5</property>
42         <property name="initialPoolSize">10</property>
43         <property name="minPoolSize">5</property>
44         <property name="maxPoolSize">20</property>
45     </named-config>
46 
47 </c3p0-config>

 

(3)編寫類文件,創建連接池

1)c3p0.properties配置文件情況下

數據庫對象的代理類(封裝Connection類的一些方法)

 1 package C3P0;
 2 
 3 import java.sql.Connection;
 4 import java.sql.ResultSet;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 
 8 import com.mchange.v2.c3p0.ComboPooledDataSource;
 9 
10 public class C3P0Util {
11 
12     private static ComboPooledDataSource ds=new ComboPooledDataSource();
13     
14     /*
15      * 獲取數據庫連接對象
16      */
17     public static Connection getConnection() throws SQLException{
18         return ds.getConnection();
19     }
20     
21     /*
22      * 封裝數據庫相關資源的關閉工作
23      */
24     public void close(ResultSet rs,Statement st,Connection conn) throws SQLException{
25         if(rs!=null){
26                 rs.close();        
27         }
28         if(st!=null){
29                 st.close();
30         }
31         if(conn!=null){
32             conn.close();
33         }
34     }    
35 }

代碼調用:

 1 package C3P0;
 2 
 3 import java.sql.Blob;
 4 import java.sql.CallableStatement;
 5 import java.sql.Connection;
 6 import java.sql.ResultSet;
 7 import java.sql.SQLException;
 8 import java.sql.Types;
 9 
10 public class C3P0Test {
11 
12     public static void main(String[] args) throws SQLException {
13         C3P0Util c3p0Util=new C3P0Util();
14         Connection conn=c3p0Util.getConnection();
15         //下面代碼是存儲過程的調用
16                 String s="call SP_select_nofilter6(?,?,?) ";
17                 CallableStatement cst=conn.prepareCall(s);
18                 cst.setInt(2, 2);
19                 cst.registerOutParameter(1, Types.VARCHAR);
20                 cst.registerOutParameter(3, Types.BLOB);
21                 ResultSet rs=cst.executeQuery();
22                 String name=cst.getString(1);
23                 Blob b=cst.getBlob(3);
24                 
25                 System.out.println("name:"+name+" Blob:"+b);
26                 //關閉資源
27                 c3p0Util.close(rs, cst, conn);
28     }
29 }

運行結果:

1 二月 14, 2017 7:36:12 下午 com.mchange.v2.log.MLog 
2 信息: MLog clients using java 1.4+ standard logging.
3 二月 14, 2017 7:36:13 下午 com.mchange.v2.c3p0.C3P0Registry 
4 信息: Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]
5 二月 14, 2017 7:36:13 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource 
6 信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 5, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 10000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> 2y4pm69mgrekqw18rvmvn|7aec35a, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2y4pm69mgrekqw18rvmvn|7aec35a, idleConnectionTestPeriod -> 600, initialPoolSize -> 10, jdbcUrl -> jdbc:mysql://127.0.0.1:3306/imooc?useUnicode=true&amp;characterEncoding=utf-8, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 600, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 15, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 3, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
7 name:xiao Blob:com.mysql.jdbc.Blob@31b7dea0

 

2) c3p0-config.xml配置文檔情況下

數據庫對象的代理類(封裝Connection類的一些方法)

 1 package C3P0;
 2 
 3 import java.sql.Connection;
 4 import java.sql.ResultSet;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 
 8 import com.mchange.v2.c3p0.ComboPooledDataSource;
 9 
10 public class C3P0Util1 {
11 
12     private static ComboPooledDataSource ds;
13     
14     /*
15      * 獲取數據庫連接對象
16      */
17     public static Connection getConnection() throws SQLException{
18         //通過代碼創建C3P0數據庫連接池
19         /*ds = new ComboPooledDataSource();
20         ds.setDriverClass("com.mysql.jdbc.Driver");
21         ds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbcstudy");
22         ds.setUser("root");
23         ds.setPassword("XDP");
24         ds.setInitialPoolSize(10);
25         ds.setMinPoolSize(5);
26         ds.setMaxPoolSize(20);*/
27         
28         //通過讀取C3P0的xml配置文件創建數據源,C3P0的xml配置文件c3p0-config.xml必須放在src目錄下
29         //ds = new ComboPooledDataSource();//使用C3P0的默認配置來創建數據源
30         ds = new ComboPooledDataSource("MySQL");//使用C3P0的命名配置來創建數據源
31         return ds.getConnection();
32     }
33     
34     /*
35      * 封裝數據庫相關資源的關閉工作
36      */
37     public void close(ResultSet rs,Statement st,Connection conn) throws SQLException{
38         if(rs!=null){
39                 rs.close();        
40         }
41         if(st!=null){
42                 st.close();
43         }
44         if(conn!=null){
45             conn.close();
46         }
47     }
48 }

代碼調用:

 1 package C3P0;
 2 
 3 import java.sql.Blob;
 4 import java.sql.CallableStatement;
 5 import java.sql.Connection;
 6 import java.sql.ResultSet;
 7 import java.sql.SQLException;
 8 import java.sql.Types;
 9 
10 public class C3P0Test1 {
11 
12     public static void main(String[] args) throws SQLException {
13         C3P0Util1 c3p0Util1=new C3P0Util1();
14         Connection conn=c3p0Util1.getConnection();
15         //下面代碼是存儲過程的調用
16                 String s="call SP_select_nofilter6(?,?,?) ";
17                 CallableStatement cst=conn.prepareCall(s);
18                 cst.setInt(2, 2);
19                 cst.registerOutParameter(1, Types.VARCHAR);
20                 cst.registerOutParameter(3, Types.BLOB);
21                 ResultSet rs=cst.executeQuery();
22                 String name=cst.getString(1);
23                 Blob b=cst.getBlob(3);
24                 
25                 System.out.println("name:"+name+" Blob:"+b);
26                 //關閉資源
27                 c3p0Util1.close(rs, cst, conn);
28     }
29 }

運行結果:

1 二月 14, 2017 8:06:03 下午 com.mchange.v2.log.MLog 
2 信息: MLog clients using java 1.4+ standard logging.
3 二月 14, 2017 8:06:03 下午 com.mchange.v2.c3p0.C3P0Registry 
4 信息: Initializing c3p0-0.9.5.2 [built 08-December-2015 22:06:04 -0800; debug? true; trace: 10]
5 二月 14, 2017 8:06:03 下午 com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource 
6 信息: Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 5, acquireRetryAttempts -> 5, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 10000, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> MySQL, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> com.mysql.jdbc.Driver, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> 2y4pm69mgsgybs1qf3g8s|6e5e91e4, idleConnectionTestPeriod -> 600, initialPoolSize -> 10, jdbcUrl -> jdbc:mysql://127.0.0.1:3306/imooc?useUnicode=true&characterEncoding=utf-8, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 600, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 20, maxStatements -> 100, maxStatementsPerConnection -> 0, minPoolSize -> 5, numHelperThreads -> 3, preferredTestQuery -> null, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> false, testConnectionOnCheckout -> false, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
7 name:xiao Blob:com.mysql.jdbc.Blob@c39f790

總結:其實不管配置文件是c3p0.properties還是c3p0-config.xml,其代碼實現部分沒有多大區別,唯一區別可能就是c3p0-config.xml情況下可以調用含參的ComboPooledDataSource(String s)構造函數,兩個都可以調用其默認的無參構造函數。

3、dbcp和c3p0不同之處

dbcp c3p0
spring組織推薦使用 Hibernate組織推薦使用
強制關閉連接或者數據庫重啟后無法自動重連 強制關閉連接或者數據庫重啟可以自動連接
沒有自動的去回收空閑連接的功能 自動回收空閑的功能
DBCP提供最大連接數

c3p0提供最大空閑時間

dbcp並沒用相應功能 c3p0可以控制數據源加載的prepareedstatement數量,並且可以設置幫助線程的數量來提升JDBC操作速度


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM