zoukankan      html  css  js  c++  java
  • 连接池

    一、为什么会产生连接池?

    我们现在考虑:

    程序中连接为什么要来管理?因为连接资源宝贵,所以我们要来对连接资源进行管理

    如何高效的来进行管理?频繁的连接,打开、关闭,这会严重影响程序的运行效率!所以我们引入连接池的概念。

    二、何为连接池?

    普通的连接:

    1. 操作数据库,创建连接。
    2. 操作结束,关闭!

    使用连接池管理:

    1. 预先创建一组连接,有的时候每次取出一个。
    2. 用完后,放回。

    连接池就好比图书馆,我们想要看书去借阅,看完之后我们要归还。就是借与还的关系。

    三、学习连接池

     3.1、自定义连接池

    /*
         *  * 自定义连接池, 管理连接
         * 代码实现:
        1.  MyPool.java  连接池类,   
        2.  指定全局参数:  初始化数目、最大连接数、当前连接、   连接池集合
        3.  构造函数:循环创建3个连接
        4.  写一个创建连接的方法
        5.  获取连接
        ------>  判断: 池中有连接, 直接拿
         ------>                池中没有连接,
    
        ------>                 判断,是否达到最大连接数; 达到,抛出异常;没有达到最大连接数,
    
        创建新的连接
        6. 释放连接
         ------->  连接放回集合中(..)
         */
        private int init_count=3;  //初始化连接数目
        private int max_count=6;   //最大连接数目
        private int current_count=0; //记录当前使用连接数目
        //连接池,存放所有的初始化连接
        private LinkedList<Connection> pool=new LinkedList<Connection>();
        
        //1.构造函数,初始化连接放入连接池
        public MyPool(){
            for(int i=0;i<init_count;i++){
                //记录当前的数目
                current_count++;
                //创建原始的连接对象,加入连接池
                pool.addLast(createConnection());
            }
        }
        
        //2. 创建一个新的连接的方法
        //使用代理模式,来监测 close方法,当关闭时候,自动加入连接池
        private Connection createConnection(){
            
            try {
                Class.forName("com.mysql.jdbc.Driver");
                final Connection conn= DriverManager.getConnection("jdbc:mysql://localhost:3306/jdbc_demo", "root", "root");
                Connection proxy=(Connection) Proxy.newProxyInstance(conn.getClass().getClassLoader(), new Class[]{Connection.class}, 
                        new InvocationHandler() {
                            
                            @Override
                            public Object invoke(Object proxy, Method method, Object[] args)
                                    throws Throwable {
                                // TODO Auto-generated method stub
                                Object result=null;
                                String name=method.getName();
                                if("close".equals(name)){
                                    if(pool.size()<init_count){
                                    System.out.println("begin:当前执行close方法开始!");
                                    // 连接放入连接池 (判断..)
                                    pool.addLast(conn);
                                    System.out.println("end: 当前连接已经放入连接池了!");
                                    }else{
                                        current_count--;
                                        conn.close();
                                    }
                                }else{
                                    method.invoke(conn, args);
                                }
                                return result;        
                            }
                            
                        }
                        );
                return proxy;
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        }
        
        
        
        //获得连接
        public Connection getConnection(){
            if(pool.size()>0){ //连接池有,直接获取
                return pool.removeFirst();
            }
            if(current_count<max_count){ //连接池没有,小于最大连接,自己创建连接
                current_count++;
                return createConnection();
            }
            throw  new RuntimeException();//没有连接使用,抛出异常
            
        }
        
        //释放连接
        public void realeaseConnection(Connection conn){
            if(pool.size()<init_count){
                pool.addLast(conn);
            }else{
                current_count--;
                try {
                    conn.close();
                } catch (SQLException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        

     为什么使用LinkedList集合?

    因为LinkedList集合含有.removeFirst()方法,这样我们可以删除第一个元素,并且返回第一个元素

    3.2开源的连接池技术

    概述:

    Sun公司约定: 如果是连接池技术,需要实现一个接口! javax.sql.DataSource;

    3.2.1、DBCP连接池

    核心类:BasicDataSource

    // 1. 硬编码方式实现连接池
            @Test
            public void testDbcp() throws Exception {
                BasicDataSource bds=new BasicDataSource(); //创建核心类
                bds.setDriverClassName("com.mysql.jdbc.Driver"); //数据库驱动
                bds.setUrl("jdbc:mysql://localhost:3306/jdbc_demo"); //数据库连接字符
                bds.setUsername("root"); //数据库用户名
                bds.setPassword("root");//数据库密码
                bds.setInitialSize(3); //初始化连接
                bds.setMaxActive(6);//最大连接数目
                bds.setMaxIdle(3000);//最大休闲时间
                String sql="select * from admin where id=5";
                //获取连接
                Connection conn=bds.getConnection();
                PreparedStatement pstmt=conn.prepareStatement(sql);
                System.out.println(pstmt.execute());
                conn.close();
            }
            
            
            // 2. 【推荐】配置方式实现连接池  ,  便于维护
            @Test
            public void testDBCP() throws Exception {
                 // 获取文件流
                InputStream inputStream=App_DBCP.class.getResourceAsStream("/db.properties");
                // 加载prop配置文件
                Properties prop=new Properties();
                prop.load(inputStream);
                
                // 根据prop配置,直接创建数据源对象
                DataSource ds=BasicDataSourceFactory.createDataSource(prop);
                String sql="select * from admin where id=5";
                //获取连接
                Connection conn=ds.getConnection();
                PreparedStatement pstmt=conn.prepareStatement(sql);
                System.out.println(pstmt.execute());
                conn.close();
            }

    配置文件为db.properties,配置文件中的keyBaseDataSouce中的属性一样:

    url=jdbc:mysql://localhost:3306/jdbc_demo
    driverClassName=com.mysql.jdbc.Driver
    username=root
    password=root
    initialSize=3
    maxActive=6
    maxIdle=3000

    3.2.1、DBCP连接池

    C3P0连接池:

    最常用的连接池技术!Spring框架,默认支持C3P0连接池技术!

    C3P0连接池,核心类:

    CombopooledDataSource ds;

    package cn.lyjs.c3p0;
    
    import static org.junit.Assert.*;
    
    import java.sql.Connection;
    
    import org.junit.Test;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    
    public class C3P0 {
        
        //1. 硬编码方式,使用C3P0连接池管理连接
        @Test
        public void testCode() throws Exception {
            // 创建连接池核心工具类
            ComboPooledDataSource dataSource=new ComboPooledDataSource();
            // 设置连接参数:url、驱动、用户密码、初始连接数、最大连接数
            dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc_demo");
            dataSource.setDriverClass("com.mysql.jdbc.Driver");
            dataSource.setUser("root");
            dataSource.setPassword("root");
            dataSource.setInitialPoolSize(3);
            dataSource.setMaxPoolSize(6);
            dataSource.setMaxIdleTime(3000);
            String sql="delete from admin where id=6";
            Connection conn=dataSource.getConnection();
            conn.prepareStatement(sql).executeUpdate();
            conn.close();
        }
        
        //2. XML配置方式,使用C3P0连接池管理连接
        @Test
        public void testXml() throws Exception {
                    // 创建c3p0连接池核心工具类
                    // 自动加载src下c3p0的配置文件【c3p0-config.xml】
            ComboPooledDataSource dataSource=new ComboPooledDataSource();
            String sql="delete from admin where id=7";
            Connection conn=dataSource.getConnection();
            conn.prepareStatement(sql).executeUpdate();
            conn.close();
        }
    }
    c3p0-config.xml,配置文件
    <c3p0-config>
        <default-config>
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_demo</property>
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="user">root</property>
            <property name="password">root</property>
            <property name="initialPoolSize">3</property>
            <property name="maxPoolSize">6</property>
            <property name="maxIdleTime">1000</property>
        </default-config>
    
    
        <named-config name="oracle_config">
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/jdbc_demo</property>
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="user">root</property>
            <property name="password">root</property>
            <property name="initialPoolSize">3</property>
            <property name="maxPoolSize">6</property>
            <property name="maxIdleTime">1000</property>
        </named-config>
    
    
    </c3p0-config>
  • 相关阅读:
    一百零二、SAP中ALV事件之十五,让ALV表格自动求和
    一百零一、SAP中ALV事件之十四,让ALV表格自动排序
    一百、SAP中ALV事件之十三,给ALV的自定义按钮添加事件
    九十九、SAP中ALV事件之十二,给ALV的标题栏添加图片
    九十八、SAP中ALV事件之十一,查看图片
    九十七、SAP中ALV事件之十,通过REUSE_ALV_COMMENTARY_WRITE函数来显示ALV的标题
    九十六、SAP中ALV事件之九,显示功能按钮栏中显示ALV加强工具栏
    九十五、SAP中查看自定义包的所有模块,对象,函数主,事务等
    二十、JavaScript之对象
    十九、JavaScript之数组
  • 原文地址:https://www.cnblogs.com/lyjs/p/5041656.html
Copyright © 2011-2022 走看看