zoukankan      html  css  js  c++  java
  • 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操作速度
  • 相关阅读:
    Validation failed for one or more entities. See 'EntityValidationErrors' property for more details
    Visual Studio断点调试, 无法监视变量, 提示无法计算表达式
    ASP.NET MVC中MaxLength特性设置无效
    项目从.NET 4.5迁移到.NET 4.0遇到的问题
    发布网站时应该把debug设置false
    什么时候用var关键字
    扩展方法略好于帮助方法
    在基类构造器中调用虚方法需谨慎
    ASP.NET MVC中商品模块小样
    ASP.NET MVC中实现属性和属性值的组合,即笛卡尔乘积02, 在界面实现
  • 原文地址:https://www.cnblogs.com/xiaotiaosi/p/6398371.html
Copyright © 2011-2022 走看看