zoukankan      html  css  js  c++  java
  • 数据库连接池

    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
        }
    }
    





  • 相关阅读:
    网易考拉海购:电商高并发架构设计的铁律
    时序数据库(TSDB)-为万物互联插上一双翅膀
    从互联网+角度看云计算的现状与未来
    四两拨千斤式的攻击!如何应对Memcache服务器漏洞所带来的DDoS攻击?
    知物由学 | AI时代,那些黑客正在如何打磨他们的“利器”?(一)
    知物由学 | AI时代,那些黑客正在如何打磨他们的“利器”?(二)
    应对羊毛党的老手段不管用了,但有些公司依然有办法,他们是怎么做的?
    微服务化的数据库设计与读写分离
    Kubernetes性能测试实践
    微服务化之无状态化与容器化
  • 原文地址:https://www.cnblogs.com/ziyue7575/p/11593475.html
Copyright © 2011-2022 走看看