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

时间:2024-01-21 22:42:21

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

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

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

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

一、 应用程序直接建立数据库连接模型

应用程序直接每次访问数据库时,都建立创建一个数据库的链接,这样每次建立这样的连接都需要耗费的资源,当同时有很多用户在使用应用程序时,可能会导致应用程序崩溃。

图为应用程序直接建立数据库连接模型

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

二、使用数据库连接池优化模型

数据库连接池的基本思路是,平时建立适量的数据库的连接,放在一个集合中,当有用户需要建立数据库连接的时候,直接到集合中取出一个数据库连接对象(Connection),这样不用再需要重新创建,这样会节省大量的资源,当用户不需要在对数据库进行访问了,那么就将数据库连接对象(Connection)重新放回到集合中,以便方便下次使用。

数据库连接池优化模型图

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

1、关于连接池中的连接数量的一些规定:

(1)最小连接数:是连接池一直保持的数据库连接,所以如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费(适量).

(2)最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中,这会影响以后的数据库操作。通常在使用完起始集合中的连接后,会再重新创建一些数据库连接对象,用来满足用户需求,但是这种新建并不是无限制的。

(3)当使用完的连接对象需要重新放回到集合中以备使用,但是超过最小连接数的连接在使用完不会马上被释放,他将被放到连接池中等待重复使用或是超时后最终被释放。

2、编写数据库连接池

简单思路为:创建一个类继承DataSource接口,在类中实现静态的加载出配置文档db.properties文档,并创建最小连接量的数据库连接对象(Connection),添加到Linkedlist(选择Linkedlist集合原因是便于增删)集合中。重写getConnection()函数,在getConnection()函数中实现数据库连接对象的获取。

db.properties文档

转  JDBC连接数据库(二)——连接池
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
转  JDBC连接数据库(二)——连接池

创建数据库连接池:

转  JDBC连接数据库(二)——连接池
  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 }
转  JDBC连接数据库(二)——连接池

进一步封装一些相关数据库的类的方法

转  JDBC连接数据库(二)——连接池
 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 }
转  JDBC连接数据库(二)——连接池

调试代码:

转  JDBC连接数据库(二)——连接池
 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 }
转  JDBC连接数据库(二)——连接池

运行结果:

转  JDBC连接数据库(二)——连接池
 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个数据库连接对象!
转  JDBC连接数据库(二)——连接池

标红的代码是比较重要的代码段~,其中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

转  JDBC连接数据库(二)——连接池
 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
转  JDBC连接数据库(二)——连接池

(3)程序实现dbcp连接

代码演示:

数据库对象的代理类(封装Connection类的一些方法)

转  JDBC连接数据库(二)——连接池
 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 }
转  JDBC连接数据库(二)——连接池

代码调用:

转  JDBC连接数据库(二)——连接池
 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 }
转  JDBC连接数据库(二)——连接池

运行结果:

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

转  JDBC连接数据库(二)——连接池
 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
转  JDBC连接数据库(二)——连接池

2)c3p0-config.xml文档

转  JDBC连接数据库(二)——连接池
 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>
转  JDBC连接数据库(二)——连接池

(3)编写类文件,创建连接池

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

数据库对象的代理类(封装Connection类的一些方法)

转  JDBC连接数据库(二)——连接池
 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 }
转  JDBC连接数据库(二)——连接池

代码调用:

转  JDBC连接数据库(二)——连接池
 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 }
转  JDBC连接数据库(二)——连接池

运行结果:

转  JDBC连接数据库(二)——连接池
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
转  JDBC连接数据库(二)——连接池

2) c3p0-config.xml配置文档情况下

数据库对象的代理类(封装Connection类的一些方法)

转  JDBC连接数据库(二)——连接池
 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 }
转  JDBC连接数据库(二)——连接池

代码调用:

转  JDBC连接数据库(二)——连接池
 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 }
转  JDBC连接数据库(二)——连接池

运行结果:

转  JDBC连接数据库(二)——连接池
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
转  JDBC连接数据库(二)——连接池

总结:其实不管配置文件是c3p0.properties还是c3p0-config.xml,其代码实现部分没有多大区别,唯一区别可能就是c3p0-config.xml情况下可以调用含参的ComboPooledDataSource(String s)构造函数,两个都可以调用其默认的无参构造函数。

3、dbcp和c3p0不同之处

dbcp c3p0
spring组织推荐使用 Hibernate组织推荐使用
强制关闭连接或者数据库重启后无法自动重连 强制关闭连接或者数据库重启可以自动连接
没有自动的去回收空闲连接的功能 自动回收空闲的功能
DBCP提供最大连接数

c3p0提供最大空闲时间

dbcp并没用相应功能 c3p0可以控制数据源加载的prepareedstatement数量,并且可以设置帮助线程的数量来提升JDBC操作速度