数据库连接池

TOC

数据库连接池

实际开发中“获得连接”或“释放资源”是非常消耗系统资源的两个过程,为了解决此类性能问题,通常情况我们采用连接池技术,来共享连接Connection。这样我们就不需要每次都创建连接、释放连接了,这些操作都交给了连接池.

  • 概念
      用池来管理Connection,这样可以重复使用Connection。有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象。当使用完Connection后,调用Connection的close()方法也不会真的关闭Connection,而是把Connection“归还”给池。池就可以再利用这个Connection对象了。
      特别是在多并发,多用户的时候,更加明显。
      ---类似线程池
  • 作用:自身维护了多个Connection连接对象维护
  • 规范:
      Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商需要让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!(接口由数据库厂商或第三方公司实现,不用我们自己写)
      常见的连接池:DBCPC3P0

自定义连接池

在javax.sql.DataSource接口--连接池的接口

  • 功能:初始化多个连接.把多个连接放入到内存中.
  • 归还:将连接对象放回到内存中.
import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedList;
import com.itheima.utils.JdbcUtils;

/**
 * 简易的连接池
 * @author Administrator
 *
 */
public class MyDataSource {
    static LinkedList<Connection> pool=new LinkedList<>();
    //创建连接池,3个连接
    static{
        //初始化的时候 需要放入3个连接---用集合,经常用,link快一点
        for (int i = 0; i < 3; i++) {
            try {
                Connection conn = JdbcUtils.getConnection();
                pool.addLast(conn);//放到最后面
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    //从连接池中获取连接
    public static Connection getConnection(){
        //获取连接的时候需要判断list是否为空
        if(pool.isEmpty()){
            //在添加3个连接进去
            for (int i = 0; i < 3; i++) {
                try {
                    Connection conn = JdbcUtils.getConnection();
                    pool.addLast(conn);
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println("从池中获取一个连接");
        return pool.removeFirst();//先进先出
    }

    //归还连接的方法
    public static void addBack(Connection conn){
        //将conn放入到list的最后面即可
        pool.addLast(conn);
        System.out.println("连接已归还");
    }
}
  • 使用案例:
import java.sql.Connection;
public class TestDs {
    public static void main(String[] args) {
         //创建连接池
         MyDataSource ds = new MyDataSource();
         //获取连接
         Connection conn=ds.getConnection();
         System.out.println(conn);
         //归还连接
         ds.addBack(conn);
    }
}
  • 存在问题:
    1.创建连接池的时候能不能面向接口编程.
    2.额外增加连接池的方法,那么程序员需要记住这些方法.能不能不额外去提供一些方法.
  • 解决:就是要去增强Connection的close方法.
    1. 继承的方法:
      条件:能够控制这个类的构造.
    2. ☆装饰者模式:(静态代理)
      (1)使用条件:
       (1.1)增强的类和被增强的类实现相同的接口.
       (1.2)在增强的类中能够获得被增强的类的引用.
      (2)接口中方法过多,只增强其中的一个方法.其他方法都需要原样调用原有方法.
  1. ☆动态代理:
    JDK的动态代理使用条件:被代理的对象必须实现接口.

使用静态代理加强连接池

//加强close方法,其他方法用之前的
import java.sql.Connection;
public class ConnectionWarp implements Connection {//继承这个接口
    private Connection conn;
    private LinkedList<Connection> list;
    public ConnectionWarp(Connection conn){
         this.conn=conn;
    }
    public ConnectionWarp(Connection conn,LinkedList<Connection> list){
         this.conn=conn;
         this.list=list;
    }
    @Override
    //不需要加强的方法 调用原来的
    public Statement createStatement() throws SQLException {
         return conn.createStatement();
    }
    @Override
    //不需要加强的方法 调用原来的
    public PreparedStatement prepareStatement(String sql) throws SQLException {
         return conn.prepareStatement(sql);
    }
    @Override
    //需要加强的方法
    public void close() throws SQLException {
         //添加到连接池中
         System.out.println("前:"+list.size());
         //System.out.println(this);//this代表的是当前连接
         list.addLast(this);//添加当前conncetion
         System.out.println("后:"+list.size());
         System.out.println("已经归还到连接池中");
    }
    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
         // TODO Auto-generated method stub
         return conn.unwrap(iface);//调用原来的方法
    }
  • 升级的连接池工具类
import java.sql.Connection;
import java.sql.SQLException;
import java.util.LinkedList;
import com.itheima.utils.JdbcUtils;
/**
 * 升级的连接池
 * @author Administrator
 *
 */
public class MyDataSource {
    static LinkedList<Connection> pool=new LinkedList<>();
    static{
         //初始化的时候 需要放入3个连接
         for (int i = 0; i < 3; i++) {
             try {
                  Connection conn = JdbcUtils.getConnection();
                  pool.addLast(conn);
             } catch (SQLException e) {
                 e.printStackTrace();
             }
         }
    }
    //从连接池中获取连接
    public static Connection getConnection(){
         //获取连接的时候需要判断list是否为空
         if(pool.isEmpty()){
             //在添加2个连接进去
             for (int i = 0; i < 3; i++) {
                  try {
                      Connection conn = JdbcUtils.getConnection();
                      pool.addLast(conn);
                  } catch (SQLException e) {
                      e.printStackTrace();
                  }
             }
         }
         System.out.println("从池中获取一个连接");
          Connection conn = pool.removeFirst();
          //将conn进行包装
          // ConnectionWarp myConn = new ConnectionWarp(conn);
          ConnectionWarp myConn = new ConnectionWarp(conn,pool);
         return myConn;//返回的是加强的连接
    }
    //归还连接的方法
    public static void addBack(Connection conn){
         //将conn放入到list的最后面即可
         pool.addLast(conn);
         System.out.println("连接已归还");
    }
}
  • 测试:
public class TestDs {
    public static void main(String[] args) throws SQLException {
         //创建连接池
         MyDataSource ds = new MyDataSource();//自己建立的简单连接池
         //获取连接
         Connection conn=ds.getConnection(); //其中的建立连接
         System.out.println(conn);
         //归还连接
         conn.close();  //加强的close
    }
}





posted @ 2019-09-26 18:02  紫月java  阅读(158)  评论(0编辑  收藏  举报