• 转 JDBC连接数据库(二)——连接池


      https://www.cnblogs.com/xiaotiaosi/p/6398371.html

    数据库保持长连接,不过一直都是idle,除非有用户激活连接,这样后果是无法删除用户,但是不影响数据库启停。

    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操作速度
  • 相关阅读:
    命名mangling(压榨)
    Redis的源代码分析
    开源数据库 Sharding 技术 (Share Nothing)
    Python中time模块详解
    关于海量数据的数据模型
    字符数组,字符指针,Sizeof总结
    ConfigParser模块的使用
    分享懒人张RDLC报表(七、八)
    VS中提示:未能启用约束。一行或多行中包含违反非空、唯一或外键约束的值。
    VS用正则表达式统计代码行数
  • 原文地址:https://www.cnblogs.com/feiyun8616/p/10553600.html
Copyright © 2020-2023  润新知