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

本文详细介绍了数据库连接池的概念、原理及其实现方式,从自定义连接池到利用装饰设计模式和适配器模式改进连接池,再到动态代理的应用。此外,文章还探讨了开源的C3P0和Druid连接池的使用,包括它们的配置和优点。
摘要由CSDN通过智能技术生成

数据库连接池的概念

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

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

自定义连接池

初探连接池

自定义JDBC工具类

配置文件 config.properties

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

JDBCUtils工具类

public class JDBCUtils {
    private JDBCUtils() {}  //构造函数私有化

    private static String driverClass;
    private static String url;
    private static String username;
    private static String password;
    private static Connection con;

    static {
        try {
            InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream("config.properties");
            Properties properties = new Properties();
            properties.load(is);
            driverClass = properties.getProperty("driverClass");
            url = properties.getProperty("url");
            username = properties.getProperty("username");
            password = properties.getProperty("password");
            Class.forName(driverClass);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    public static Connection getConnection() {  //获取连接对象
        try {
            con = DriverManager.getConnection(url, username, password);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return con;
    }
    //关闭连接(有查询结果集)
    public static void close(Connection con, Statement stat, ResultSet res) {
        if (con != null) {
            try {
                con.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (stat != null) {
            try {
                stat.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (res != null) {
            try {
                res.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
    //关闭连接(无查询结果集)
    public static void close(Connection con, Statement stat) {
        close(con, stat, 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
      public void close() throws SQLException {
          pool.add(con);
      }
  }</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值