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

本文介绍了数据库连接池的概念,探讨了自定义数据库连接池的实现,包括配置文件、JDBC工具类、各种设计模式的改进,如装饰设计模式和适配器设计模式。同时,详细讲解了C3P0和Druid这两个开源连接池的使用,包括配置文件设置和连接获取。最后,提出了抽取工具类以优化代码复用。
摘要由CSDN通过智能技术生成

数据库连接池的概念

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

 

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

 

自定义连接池

初探连接池

自定义JDBC工具类

配置文件 config.properties

driverClass=com.mysql.jdbc.Driverurl=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());    }}

输出:

使用前连接池数量:10ename:SMITH job:CLERK hiredate:1980-12-17ename:ALLEN job:SALESMAN hiredate:1981-02-20ename:WARD job:SALESMAN hiredate:1981-02-22ename:JONES job:MANAGER hiredate:1981-04-02ename:MARTIN job:SALESMAN hiredate:1981-09-28ename:BLAKE job:MANAGER hiredate:1981-05-01ename:CLARK job:MANAGER hiredate:1981-06-09ename:SCOTT job:ANALYST hiredate:1987-04-19ename:KING job:PRESIDENT hiredate:1981-11-17ename:TURNER job:SALESMAN hiredate:1981-09-08ename:ADAMS job:CLERK hiredate:1987-05-23ename:JAMES job:CLERK hiredate:1981-12-03ename:FORD job:ANALYST hiredate:1981-12-03ename: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()方法,将连接
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值