连接池

作者: Dl_毛良伟 | 来源:发表于2017-05-04 11:51 被阅读80次

    - 自定义连接池

    普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码(得花费0.05s~1s的时间)。需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。数据库的连接资源并没有得到很好的重复利用.若同时有几百人甚至几千人在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。连接池可以避免这些问题
    实现步骤:

    1. 指定全局参数 : 初始化数目 最大连接数 当前连接 连接池集合
    2. 在构造函数中 : 循环创建三个连接
    3. 实现一个创建连接的方法
    4. 获取连接
    5. 关闭连接

    代码部分:

    package com.demo01.test;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.SQLException;
    import java.util.LinkedList;
    
    /**
     * Created by pc on 17-5-1.
     */
    public class MyPool {
        private int init_count = 3;  //初始化链接数目
        private int max_count = 6;   //最大连接数目
        private int current_count;   //记录连接数
        //连接池,存放所有初始化连接
        private LinkedList<Connection> pool = new LinkedList<Connection>();
    
        //1.构造函数中将初始化连接放入连接池中
        public MyPool() {
            //初始化连接
            for (int i = 0; i < init_count; i++) {
                //记录当前连接条数
                current_count++;
                //把连接放入连接池中
                pool.addLast(createConnection());
            }
        }
    
        //2.创建一个新的连接对象
        public Connection createConnection() {
            try {
                Class.forName("com.mysql.jdbc.Driver");
                return DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbcdemo", "root", "root");
            } catch (ClassNotFoundException e) {
                throw new RuntimeException(e);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return null;
        }
    
        //3.获取连接
        public Connection getConnection() {
            //判断连接池是否有连接,如果有则直接取出
            if (pool.size() > 0) {
                return pool.removeFirst();
            }
            //如果连接池的连接以取完,判断是否超过最大连接数,如果没有则创建
            if (current_count < max_count) {
                current_count++;
                return createConnection();
            }
            //如果超过最大连接数,则抛出异常
            throw new RuntimeException("超过最大连接数");
        }
    
        //4.释放链接
        public void realeaseConnection(Connection connection) throws SQLException {
            //如果连接池没有放满连接,则将该链接放回连接池
            if (current_count < pool.size()) {
                pool.addLast(connection);
                current_count--;
            } else {
                connection.close();
                current_count--;
            }
        }
    
    }
    
    

    - DBCP连接池

    DBCP(DataBase connection pool)数据库连接池是 apache 上的一个Java连接池项目。DBCP通过连接池预先同数据库建立一些连接放在内存中(即连接池中),应用程序需要建立数据库连接时直接到从接池中申请一个连接使用,用完后由连接池回收该连接,从而达到连接复用,减少资源消耗的目的。
    引入jar文件,使用maven配置这两个文件:

    • commons-dbcp2
    • commons-pool2
            <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-dbcp2</artifactId>
                <version>2.0.1</version>
            </dependency>
    
    
            <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-pool2 -->
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
                <version>2.2</version>
            </dependency>
    
    
    

    代码部分

    package com.demo01.test;
    
    import org.apache.commons.dbcp2.BasicDataSource;
    import org.junit.Test;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    
    /**
     * Created by pc on 17-5-1.
     */
    public class Test_dbcp {
    
        @Test
        public void testDbcp() throws SQLException {
            //DBCP连接池核心
            BasicDataSource dataSource = new BasicDataSource();
    
            //连接池参数配置:初始化连接数,最大连接数  /连接字符串,驱动,用户,密码
            dataSource.setUrl("jdbc:mysql:///jdbcdemo?useUnicode=true&characterEncoding=utf-8");
            dataSource.setDriverClassName("com.mysql.jdbc.Driver");
            dataSource.setUsername("root");
            dataSource.setPassword("root");
            dataSource.setInitialSize(3);
            dataSource.setMaxIdle(3000);
            //dataSource.setMaxTotal(6);
            //获取连接
            Connection conn = dataSource.getConnection();
            conn.prepareStatement("delete FROM admin where id=9").executeUpdate();
    
            //关闭连接
            conn.close();
        }
    
    }
    
    
    image.png

    - c3p0连接池

    c3p0与dbcp区别
    dbcp没有自动回收空闲连接的功能
    c3p0有自动回收空闲连接功能
    demo

    package demo01.utils;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    import org.junit.Test;
    
    import java.sql.Connection;
    
    public class demo {
    
        @Test
        //1. 硬编码方式,使用C3P0连接池管理连接
        public void testCode() throws Exception {
            // 创建连接池核心工具类
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            // 设置连接参数:url、驱动、用户密码、初始连接数、最大连接数
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbcdemo");
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setUser("root");
            dataSource.setPassword("root");
            dataSource.setInitialPoolSize(3);
            dataSource.setMaxPoolSize(6);
            dataSource.setMaxIdleTime(1000);
    
            // ---> 从连接池对象中,获取连接对象
            Connection con = dataSource.getConnection();
            // 执行更新
            con.prepareStatement("delete from admin where id=7").executeUpdate();
            // 关闭
            con.close();
        }
    
        @Test
        //2. XML配置方式,使用C3P0连接池管理连接
        public void testXML() throws Exception {
            // 创建c3p0连接池核心工具类
            ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默认的配置
    
            // 获取连接
            Connection con = dataSource.getConnection();
            // 执行更新
            con.prepareStatement("delete from admin where id=5").executeUpdate();
            // 关闭
            con.close();
    
        }
    }
    
    
    原始数据表
    操作后的数据表

    相关文章

      网友评论

      • 6d96978eeefb:异常处理不太好,当出现连不上的时候,你是打印的错误日志,并且返回了一个null,放到了池子里,但是后面又没有对这个null进行任何的判断,就直接使用了。

        你需要思考一下,这里的异常我们应该怎么处理最好?
        6d96978eeefb: @Dl_毛良伟 另外学习一个东西都是有一个目标的,就是你为什么要学这个东西,你期望学到什么程度,能解决什么问题,只要到达了目标就可以停止了,而不是漫无目的的一直往前钻,这样反而是非常低效的学习
        6d96978eeefb: @Dl_毛良伟 当你觉得再继续往下学很艰难的时候,就可以停下来了,当然要把发现的问题留个记号,等到以后知识更全面的时候,再继续解决
        Dl_毛良伟: @TW李鹏 嗯,谢谢老师的细心点评,就我现在而言,我还不能确定我应该怎么去学一个新知识,应不应该去深入的学习,还是知道他的用法就行了,在以后再去慢慢填充这些不足?
      • 6d96978eeefb:Class.forName("com.mysql.jdbc.Driver");

        这行代码只需要调用一次,还是每一次都需要调用?
      • 6d96978eeefb:另外你的代码不是线程安全的,可以说明一下
      • 6d96978eeefb:return createConnection();

        你这里新生成的连接不用放到池子里了吗?

      本文标题:连接池

      本文链接:https://www.haomeiwen.com/subject/wgxqtxtx.html