jdbc数据库连接池

 编写连接池需实现java.sql.DataSource接口。DataSource接口中定义了两个重载的getConnection方法:

  • Connection getConnection()
  • Connection getConnection(String username, String password)

  实现DataSource接口,并实现连接池功能的步骤:

  1. 在DataSource构造函数中批量创建与数据库的连接,并把创建的连接加入LinkedList对象中。
  2. 实现getConnection方法,让getConnection方法每次调用时,从LinkedList中取一个Connection返回给用户。
  3. 当用户使用完Connection,调用Connection.close()方法时,Collection对象应保证将自己返回到LinkedList中,而不要把conn还给数据库。Collection保证将自己返回到LinkedList中是此处编程的难点

 数据库连接池核心代码

  使用动态代理技术构建连接池中的connection

复制代码
 1 proxyConn = (Connection) Proxy.newProxyInstance(this.getClass()
 2             .getClassLoader(), conn.getClass().getInterfaces(),
 3             new InvocationHandler() {
 4         //此处为内部类,当close方法被调用时将conn还回池中,其它方法直接执行
 5             public Object invoke(Object proxy, Method method,
 6                       Object[] args) throws Throwable {
 7                 if (method.getName().equals("close")) {
 8                     pool.addLast(conn);
 9                     return null;
10             }
11             return method.invoke(conn, args);
12         }
13     });
复制代码

数据库连接池编写范例:

复制代码
  1 package me.gacl.demo;
  2 
  3 import java.io.InputStream;
  4 import java.io.PrintWriter;
  5 import java.lang.reflect.InvocationHandler;
  6 import java.lang.reflect.Method;
  7 import java.lang.reflect.Proxy;
  8 import java.sql.Connection;
  9 import java.sql.DriverManager;
 10 import java.sql.SQLException;
 11 import java.util.LinkedList;
 12 import java.util.Properties;
 13 import javax.sql.DataSource;
 14 
 15 /**
 16 * @ClassName: JdbcPool
 17 * @Description:编写数据库连接池
 18 * @author: 孤傲苍狼
 19 * @date: 2014-9-30 下午11:07:23
 20 *
 21 */ 
 22 public class JdbcPool implements DataSource{
 23 
 24     /**
 25     * @Field: listConnections
 26     *         使用LinkedList集合来存放数据库链接,
 27     *        由于要频繁读写List集合,所以这里使用LinkedList存储数据库连接比较合适
 28     */ 
 29     private static LinkedList<Connection> listConnections = new LinkedList<Connection>();
 30     
 31     static{
 32         //在静态代码块中加载db.properties数据库配置文件
 33         InputStream in = JdbcPool.class.getClassLoader().getResourceAsStream("db.properties");
 34         Properties prop = new Properties();
 35         try {
 36             prop.load(in);
 37             String driver = prop.getProperty("driver");
 38             String url = prop.getProperty("url");
 39             String username = prop.getProperty("username");
 40             String password = prop.getProperty("password");
 41             //数据库连接池的初始化连接数大小
 42             int jdbcPoolInitSize =Integer.parseInt(prop.getProperty("jdbcPoolInitSize"));
 43             //加载数据库驱动
 44             Class.forName(driver);
 45             for (int i = 0; i < jdbcPoolInitSize; i++) {
 46                 Connection conn = DriverManager.getConnection(url, username, password);
 47                 System.out.println("获取到了链接" + conn);
 48                 //将获取到的数据库连接加入到listConnections集合中,listConnections集合此时就是一个存放了数据库连接的连接池
 49                 listConnections.add(conn);
 50             }
 51             
 52         } catch (Exception e) {
 53             throw new ExceptionInInitializerError(e);
 54         }
 55     }
 56     
 57     @Override
 58     public PrintWriter getLogWriter() throws SQLException {
 59         // TODO Auto-generated method stub
 60         return null;
 61     }
 62 
 63     @Override
 64     public void setLogWriter(PrintWriter out) throws SQLException {
 65         // TODO Auto-generated method stub
 66         
 67     }
 68 
 69     @Override
 70     public void setLoginTimeout(int seconds) throws SQLException {
 71         // TODO Auto-generated method stub
 72         
 73     }
 74 
 75     @Override
 76     public int getLoginTimeout() throws SQLException {
 77         // TODO Auto-generated method stub
 78         return 0;
 79     }
 80 
 81     @Override
 82     public <T> T unwrap(Class<T> iface) throws SQLException {
 83         // TODO Auto-generated method stub
 84         return null;
 85     }
 86 
 87     @Override
 88     public boolean isWrapperFor(Class<?> iface) throws SQLException {
 89         // TODO Auto-generated method stub
 90         return false;
 91     }
 92 
 93     /* 获取数据库连接
 94      * @see javax.sql.DataSource#getConnection()
 95      */
 96     @Override
 97     public Connection getConnection() throws SQLException {
 98         //如果数据库连接池中的连接对象的个数大于0
 99         if (listConnections.size()>0) {
100             //从listConnections集合中获取一个数据库连接
101             final Connection conn = listConnections.removeFirst();
102             System.out.println("listConnections数据库连接池大小是" + listConnections.size());
103             //返回Connection对象的代理对象
104             return (Connection) Proxy.newProxyInstance(JdbcPool.class.getClassLoader(), conn.getClass().getInterfaces(), new InvocationHandler(){
105                 @Override
106                 public Object invoke(Object proxy, Method method, Object[] args)
107                         throws Throwable {
108                     if(!method.getName().equals("close")){
109                         return method.invoke(conn, args);
110                     }else{
111                         //如果调用的是Connection对象的close方法,就把conn还给数据库连接池
112                         listConnections.add(conn);
113                         System.out.println(conn + "被还给listConnections数据库连接池了!!");
114                         System.out.println("listConnections数据库连接池大小为" + listConnections.size());
115                         return null;
116                     }
117                 }
118             });
119         }else {
120             throw new RuntimeException("对不起,数据库忙");
121         }
122     }
123 
124     @Override
125     public Connection getConnection(String username, String password)
126             throws SQLException {
127         return null;
128     }
129 }
复制代码

注意:

 

db.properties配置文件如下:

1 driver=com.mysql.jdbc.Driver
2 url=jdbc:mysql://localhost:3306/jdbcStudy
3 username=root
4 password=XDP
5 
6 jdbcPoolInitSize=10

写一个JdbcUtil测试数据库连接池

复制代码
 1 package me.gacl.utils;
 2 
 3 import java.sql.Connection;
 4 import java.sql.ResultSet;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 import me.gacl.demo.JdbcPool;
 8 
 9 public class JdbcUtil {
10     
11     /**
12     * @Field: pool
13     *          数据库连接池
14     */ 
15     private static JdbcPool pool = new JdbcPool();
16     
17     /**
18     * @Method: getConnection
19     * @Description: 从数据库连接池中获取数据库连接对象
20     * @Anthor:孤傲苍狼
21     * @return Connection数据库连接对象
22     * @throws SQLException
23     */ 
24     public static Connection getConnection() throws SQLException{
25         return pool.getConnection();
26     }
27     
28     /**
29     * @Method: release
30     * @Description: 释放资源,
31     * 释放的资源包括Connection数据库连接对象,负责执行SQL命令的Statement对象,存储查询结果的ResultSet对象
32     * @Anthor:孤傲苍狼
33     *
34     * @param conn
35     * @param st
36     * @param rs
37     */ 
38     public static void release(Connection conn,Statement st,ResultSet rs){
39         if(rs!=null){
40             try{
41                 //关闭存储查询结果的ResultSet对象
42                 rs.close();
43             }catch (Exception e) {
44                 e.printStackTrace();
45             }
46             rs = null;
47         }
48         if(st!=null){
49             try{
50                 //关闭负责执行SQL命令的Statement对象
51                 st.close();
52             }catch (Exception e) {
53                 e.printStackTrace();
54             }
55         }
56         
57         if(conn!=null){
58             try{
59                 //关闭Connection数据库连接对象
60                 conn.close();
61             }catch (Exception e) {
62                 e.printStackTrace();
63             }
64         }
65     }
66 }
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值