「MySQL」自定义数据库连接池和开源数据库连接池的使用

本文探讨了数据库连接池的重要性,介绍了自定义数据库连接池的实现,包括使用装饰设计模式和适配器设计模式进行优化,以及遇到的问题。同时,详细讲解了开源的C3P0和Druid连接池的配置与使用,强调了动态代理在连接池中的应用。
摘要由CSDN通过智能技术生成

数据库连接池的概念

  • 数据库连接背景数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。
  • 数据库连接池数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。这项技术能明显提高对数据库操作的性能。
  • 数据库连接池的原理没有使用数据库连接池:一个访问创建一个连接,使用完关闭连接。而频繁的创建和关闭连接非常耗时

  • 使用数据库连接池之后:提前准备一些数据库连接,使用时从池中取出,用完归还连接池


自定义连接池
初探连接池
自定义JDBC工具类
配置文件 config.properties

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://主机名:3306/数据库名
username=用户名
password=密码

JDBCUtils工具类

Connection getConnection();  //获取数据库连接对象

public class MyDataSource implements DataSource{
    //定义集合容器,用于保存多个数据库连接对象
    //使用Collections 工具类实现集合的线程同步
    private static List<Connection> pool = Collections.synchronizedList(new ArrayList<Connection>());

    //静态代码块,生成10个数据库连接保存到集合中
    static {
        for (int i = 0; i < 10; i++) {
            Connection con = JDBCUtils.getConnection();
            pool.add(con);
        }
    }

    //返回连接池的大小
    public int getSize() {
        return pool.size();
    }

    //从池中返回一个数据库连接
    @Override
    public Connection getConnection() {
        if(pool.size() > 0) {
            //从池中获取数据库连接
            return pool.remove(0);
        }else {
            throw new RuntimeException("连接数量已用尽");
        }
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}


实现连接池类
定义一个连接池类并实现 java.sql.DataSource 接口。
 

Connection getConnection();  //获取数据库连接对象

public class MyDataSource implements DataSource{
    //定义集合容器,用于保存多个数据库连接对象
    //使用Collections 工具类实现集合的线程同步
    private static List<Connection> pool = Collections.synchronizedList(new ArrayList<Connection>());

    //静态代码块,生成10个数据库连接保存到集合中
    static {
        for (int i = 0; i < 10; i++) {
            Connection con = JDBCUtils.getConnection();
            pool.add(con);
        }
    }

    //返回连接池的大小
    public int getSize() {
        return pool.size();
    }

    //从池中返回一个数据库连接
    @Override
    public Connection getConnection() {
        if(pool.size() > 0) {
            //从池中获取数据库连接
            return pool.remove(0);
        }else {
            throw new RuntimeException("连接数量已用尽");
        }
    }

    @Override
    public Connection getConnection(String username, String password) throws SQLException {
        return null;
    }

    @Override
    public <T> T unwrap(Class<T> iface) throws SQLException {
        return null;
    }

    @Override
    public boolean isWrapperFor(Class<?> iface) throws SQLException {
        return false;
    }

    @Override
    public PrintWriter getLogWriter() throws SQLException {
        return null;
    }

    @Override
    public void setLogWriter(PrintWriter out) throws SQLException {

    }

    @Override
    public void setLoginTimeout(int seconds) throws SQLException {

    }

    @Override
    public int getLoginTimeout() throws SQLException {
        return 0;
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

自定义连接池的测试

public class MyDataSourceTest {
    public static void main(String[] args) throws SQLException {
        MyDataSource dataSource = new MyDataSource();
        System.out.println("使用前连接池数量:" + dataSource.getSize());

        Connection con = dataSource.getConnection();

        String sql = "select * from emp";

        PreparedStatement pst = con.prepareStatement(sql);

        ResultSet res = pst.executeQuery();
        while (res.next()) {
            String ename = res.getString("ename");
            String job = res.getString("job");
            String hiredate = res.getString("hiredate");
            System.out.println("ename:" + ename + "\t job:" + job + "\t hiredate:" + hiredate);
        }

        res.close();
        pst.close();
        con.close();
        System.out.println("使用后连接池数量:" + dataSource.getSize());
    }
}

输出:

使用前连接池数量:10
ename:SMITH	 job:CLERK	 hiredate:1980-12-17
ename:ALLEN	 job:SALESMAN	 hiredate:1981-02-20
ename:WARD	 job:SALESMAN	 hiredate:1981-02-22
ename:JONES	 job:MANAGER	 hiredate:1981-04-02
ename:MARTIN	 job:SALESMAN	 hiredate:1981-09-28
ename:BLAKE	 job:MANAGER	 hiredate:1981-05-01
ename:CLARK	 job:MANAGER	 hiredate:1981-06-09
ename:SCOTT	 job:ANALYST	 hiredate:1987-04-19
ename:KING	 job:PRESIDENT	 hiredate:1981-11-17
ename:TURNER	 job:SALESMAN	 hiredate:1981-09-08
ename:ADAMS	 job:CLERK	 hiredate:1987-05-23
ename:JAMES	 job:CLERK	 hiredate:1981-12-03
ename:FORD	 job:ANALYST	 hiredate:1981-12-03
ename:MILLER	 job:CLERK	 hiredate:1982-01-23
使用后连接池数量:9

问题:虽然我们自定义了数据库连接池,但是连接关闭以后并没有归还给数据库连接池,还需要改进 归还连接 的问题

继承方式改进连接池

System.out.println(JDBCUtils.getConnection());
//com.mysql.jdbc.JDBC4Connection@470e2030

通过输出 Connection 的地址发现 Connection 类的实现类是 JDBC4Connection ,是否能够通过编写一个类继承 JDBC4Connection ,然后重写 close() 方法,在关闭连接的同时归还连接?

/*
      自定义Connection类
   */
  public class MyConnection1 extends JDBC4Connection {
      //声明连接对象和连接池集合对象
      private Connection con;
      private List<Connection> pool;
  
      //通过构造方法给成员变量赋值
      public MyConnection1(String hostToConnectTo, int portToConnectTo, Properties info, String databaseToConnectTo, String url,Connection con,List<Connection> pool) throws SQLException {
          super(hostToConnectTo, portToConnectTo, info, databaseToConnectTo, url);
          this.con = con;
          this.pool = pool;
      }
  
      //重写close()方法,将连接归还给池中
      @Override
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值