精华内容
下载资源
问答
  • jdbc连接池
    2022-05-04 16:12:16

    一.什么是JDBC连接池

    概念:存放数据库连接的一个容器(集合)Connection
    

    当系统运行起来之后,这个连接池就被创建,在这个连接池当中,会申请一些对象,当有用户来访问数据库的时候,就从这个连接池当中获取连接对象,用户访问结束之后,连接池对象会归还给容器

    二.为什么要用JDBC连接池

    普通的JDBC数据库连接(Connectiond对象)使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证用户名和密码(得花费0.05s~1s的时间),数据库的连接是比较昂贵的(创建的成本比较大)。

    需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间。
    
    数据库的连接资源并没有得到很好的重复利用.若同时有几百人甚至几千人在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。
    

    三.JDBC连接池的作用

    因为建立数据库连接是一个非常耗时、耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去,极大的提高了数据库连接的性能问题,节省了资源和时间。

    Java数据库连接JDBC :jdbc就是Java数据库链接,原名Java data base connectivity

    四.JDBC连接池的使用

    大体上可以分为两类:

    一.自定义连接池:

     1.创建一个类实现javax.jdbc.dataSource 类 。
     2.创建一个 存放多个连接的容器 ,因为需要经常删除 ,查         找  。   这里用LinkedList   容器。
     3.在MyDataSource类中静态代码块中创建多个连接,添加到连接池容器中  (这里面创建连接可以直接使用 com.jdbc.connection包中的jdbcConnection 中的静态方法getConnection
     4.重写Datasource 方法中的 getConnection()  方法  
     5在MyDataSource方法中添加  一个 把当前连接归还给连接池的方法
    

    二.使用开源的数据库连接池

    1、JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,该接口通常由服务器(Weblogic, WebSphere, Tomcat)提供实现,也有一些开源组织提供实现:
    1.C3P0

    C3P0是一个开源的JDBC连接池,它实现了数据源和JNDI绑定,支持JDBC3规范 和JDBC2的标准扩展。目前使用它的开源项目有Hibernate,Spring等。

    c3p0所需jar:c3p0-0.9.2.1.jar mchange-commons-java-0.2.3.4.jar

    2.DBCP

    DBCP(DataBase connection pool),数据库连接池。是 apache 上的一个 java 连接 池项目,也是 tomcat 使用的连接池组件。
    使用dbcp需要2个包:commons-dbcp.jar,commons-pool.jar由于建立数据库连接是一个非常耗时耗资源的行为,所以通过连接池预先同数据库建立一些连接,放在内存中,应用程序需要建立数据库连接时直接到连接池中申请一个就行,用完后再放回去。

    3.Proxool

    Proxool是一种Java数据库连接池技术。sourceforge下的一个开源项目,这个项目提供一个健壮、易用的连接池,最为关键的是这个连接池提供监控的功能,方便易用,便于发现连接泄漏的情况。

    4.BoneCP

    是一个开源组织提供的数据库连接池,速度快。

    5.Druid

    是阿里提供的数据库连接池,据说是集DBCP 、C3P0 、Proxool优点于一身的数据库连接池,但是速度不确定是否有BoneCP快。

    2、DataSource 通常被称为数据源,它包含连接池和连接池管理两个部分,习惯上也经常把 DataSource 称为连接池

    3、DataSource用来取代DriverManager来获取Connection,获取速度快,同时可以大幅度提高数据库访问速度。

    以Druid(德鲁伊)数据库连接池作为例子:

    import javax.sql.DataSource; import
    com.alibaba.druid.pool.DruidDataSourceFactory;
    
    public class TestDruid { 	public static void main(String[] args)
    throws Exception { 		Properties pro = new Properties();		
    pro.load(TestDruid.class.getClassLoader().getResourceAsStream("druid.properties"));
    		DataSource ds = DruidDataSourceFactory.createDataSource(pro);
    		Connection conn = ds.getConnection(); 		System.out.println(conn); 	}
    } ```
    

    src下的配置文件为:(druid.properties):

    url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
    username=root password=123456 driverClassName=com.mysql.jdbc.Driver
    
    initialSize=10 maxActive=20 maxWait=1000 filters=wall ```
    
    更多相关内容
  • 使用java技术实现jdbc连接池 包括了全面的jar和cp30,commons-DBCP,c3p0 for linux的包,以及jdbc jars
  • 一款小型JDBC连接池组件,具有性能高,代码轻,稳定好的特点。 一款小型JDBC连接池组件,具有性能高,代码轻,稳定好的特点。 一款小型JDBC连接池组件,具有性能高,代码轻,稳定好的特点。 一款小型JDBC连接...
  • jdbc连接池属性介绍

    2018-11-22 10:11:08
    jdbc连接池属性介绍,
  • JDBC连接池详解

    千次阅读 2022-03-29 11:44:32
    文章目录一、JDBC数据库连接池的必要性二、数据库连接池技术1、数据库连接池的基本思想:2、数据库连接池的工作原理:3、数据库连接池技术的优点:三、多种开源的数据库连接池 一、JDBC数据库连接池的必要性 1、在...


    一、JDBC数据库连接池的必要性

    1、在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤:

    (1)在主程序(如servlet、beans)中建立数据库连接
    (2)进行sql操作
    (3)断开数据库连接

    2、这种模式开发,存在的问题:

    (1)普通的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection加载到内存中,再验证用户名和密码(得花费0.05s~1s的时间)。需要数据库连接的时候,就向数据库要求一个,执行完成后再断开连接。这样的方式将会消耗大量的资源和时间数据库的连接资源并没有得到很好的重复利用。若同时有几百人甚至几千人在线,频繁的进行数据库连接操作将占用很多的系统资源,严重的甚至会造成服务器的崩溃。
    (2)对于每一次数据库连接,使用完后都得断开。否则,如果程序出现异常而未能关闭,将会导致数据库系统中的内存泄漏,最终将导致重启数据库。(回忆:何为Java的内存泄漏?)
    (3)这种开发不能控制被创建的连接对象数,系统资源会被毫无顾及的分配出去,如连接过多,也可能导致内存泄漏,服务器崩溃。

    二、数据库连接池技术

    为解决传统开发中的数据库连接问题,可以采用数据库连接池技术。

    1、数据库连接池的基本思想:

    就是为数据库连接建立一个“缓冲池”。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从“缓冲池”中取出一个,使用完毕之后再放回去。

    数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个。

    数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数来设定的。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量。连接池的最大数据库连接数量限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中。

    在这里插入图片描述

    2、数据库连接池的工作原理:

    在这里插入图片描述

    3、数据库连接池技术的优点:

    (1)资源重用
    由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销。在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性。

    (2)更快的系统反应速度
    数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间

    (3)新的资源分配手段
    对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置,实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源

    (4)统一的连接管理,避免数据库连接泄漏
    在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露

    三、多种开源的数据库连接池

    1、JDBC 的数据库连接池使用 javax.sql.DataSource 来表示,DataSource 只是一个接口,该接口通常由服务器(Weblogic, WebSphere, Tomcat)提供实现,也有一些开源组织提供实现

    (1)DBCP 是Apache提供的数据库连接池。tomcat服务器自带dbcp数据库连接池。速度相对c3p0较快,但因自身存在BUG,Hibernate3已不再提供支持。

    (2)C3P0 是一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以,hibernate官方推荐使用。

    (3)Proxool 是sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点.

    (4)BoneCP 是一个开源组织提供的数据库连接池,速度快。

    (5)Druid 是阿里提供的数据库连接池,据说是集DBCP 、C3P0
    Proxool优点于一身的数据库连接池,但是速度不确定是否有BoneCP快。

    2、DataSource 通常被称为数据源,它包含连接池和连接池管理两个部分,习惯上也经常把 DataSource 称为连接池

    3、DataSource用来取代DriverManager来获取Connection,获取速度快,同时可以大幅度提高数据库访问速度。

    特别注意:

    (1)数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可。
    (2)当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close();
    但conn.close()并没有关闭数据库的物理连接,它仅仅把数据库连接释放,归还给了数据库连接池。

    展开全文
  • 自定义的JDBC连接池,支持并发访问,可维持多个数据库的连接池
  • java JDBC连接池

    2013-09-03 11:51:57
    包括JDBC连接池的相关代码和xml配置文件。
  • jdbc数据库连接池,方便连接数据库,优化数据库连接速度。
  • 完美的java jdbc连接池实例.zip
  • java jdbc 连接池实例 项目只要配数据源就可以直接启用, 也可以整合到你个项目里面, 可oracle、mysql、sqlserver自由切换方言。
  • jdbc连接池

    2012-01-04 22:01:04
    jdbc连接池设计,里面包含jdom.jar包,只需将此放入到新建的java项目中,运行test.java
  • Java学习——JDBC连接池

    千次阅读 热门讨论 2021-06-08 09:52:35
    JDBC数据库连接池 1.概念: 数据库连接池其实就是一个容器(集合),存放数据库连接的容器。因为每次创建一个数据库链接都是一次极大的资源消费,所以连接复用。通过建立一个数据库连接池以及一套连接使用管理策略...

    JDBC数据库连接池

        1.概念:

                数据库连接池其实就是一个容器(集合),存放数据库连接的容器。因为每次创建一个数据库链接都是一次极大的资源消费,所以连接复用。通过建立一个数据库连接池以及一套连接使用管理策略,可以使一个数据库连接可以得到高效、安全的复用,能避免了数据库连接频繁建立、关闭的开销。

                当系统初始化好后,容器被创建,容器中会申请一些连接对象,当用户来访问数据库时,从容器中获取连接对象,用户访问完之后,会将连接对象归还给容器。

        2. 使用好处:

            1. 节约资源

            2. 用户访问高效

        3. 如何实现:

            1. 标准接口:DataSource   javax.sql包下的
                1. 方法:
                    * 获取连接:getConnection()
                    * 归还连接:Connection.close()。如果连接对象Connection是从连接池中获取的,那么调用Connection.close()方法,则不会再关闭连接了。而是归还连接

            2. 一般我们不去实现它,有数据库厂商来实现
                1. C3P0:数据库连接池技术
                2. Druid:数据库连接池实现技术,由阿里巴巴提供的

        4. C3P0:数据库连接池技术

            * 步骤
                        1. 导入jar包 (两个) c3p0-0.9.5.2.jar mchange-commons-java-0.2.12.jar ,
                            * 不要忘记导入数据库驱动jar包
                        2. 定义配置文件:
                            * 名称: c3p0.properties 或者 c3p0-config.xml
                            * 路径:直接将文件放在src目录下即可。

    <c3p0-config>
      <!-- 使用默认的配置读取连接池对象 -->
      <default-config>
      	<!--  连接参数 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/db4</property>
        <property name="user">root</property>
        <property name="password">root</property>
        
        <!-- 连接池参数 -->
        <!--初始化申请的连接数量-->
        <property name="initialPoolSize">5</property>
        <!--最大的连接数量-->
        <property name="maxPoolSize">10</property>
        <!--超时时间-->
        <property name="checkoutTimeout">3000</property>
      </default-config>
    
      <named-config name="otherc3p0"> 
        <!--  连接参数 -->
        <property name="driverClass">com.mysql.jdbc.Driver</property>
        <property name="jdbcUrl">jdbc:mysql://localhost:3306/db3</property>
        <property name="user">root</property>
        <property name="password">root</property>
        
        <!-- 连接池参数 -->
        <property name="initialPoolSize">5</property>
        <property name="maxPoolSize">8</property>
        <property name="checkoutTimeout">1000</property>
      </named-config>
    </c3p0-config>

                        3. 创建核心对象 数据库连接池对象 ComboPooledDataSource
                        4. 获取连接: getConnection
            * 代码:     

    //1.创建数据库连接池对象
    DataSource ds  = new ComboPooledDataSource();
    //2. 获取连接对象
    Connection conn = ds.getConnection();

        5. Druid:数据库连接池实现技术,由阿里巴巴提供的        

            1. 步骤:
                        1. 导入jar包 druid-1.0.9.jar
                        2. 定义配置文件:

                            * 是properties形式的
                            * 可以叫任意名称,可以放在任意目录下

    driverClassName=com.mysql.jdbc.Driver
    url=jdbc:mysql:///db3
    username=root
    password=root
    # 初始化连接数量
    initialSize=5
    # 最大连接数
    maxActive=10
    # 最大等待时间
    maxWait=3000

                        3. 加载配置文件。Properties
                        4. 获取数据库连接池对象:通过工厂来来获取  DruidDataSourceFactory
                        5. 获取连接:getConnection

            * 代码:

    //3.加载配置文件
    Properties pro = new Properties();
    InputStream is = DruidDemo.class.getClassLoader().getResourceAsStream("druid.properties");
    pro.load(is);
    //4.获取连接池对象
    DataSource ds = DruidDataSourceFactory.createDataSource(pro);
    //5.获取连接
    Connection conn = ds.getConnection();

            2. 定义工具类
                        1. 定义一个类 JDBCUtils
                        2. 提供静态代码块加载配置文件,初始化连接池对象
                        3. 提供方法

                            1. 获取连接方法:通过数据库连接池获取连接
                            2. 释放资源
                            3. 获取连接池的方法
    * 代码:

    public class JDBCUtils {
    
                    //1.定义成员变量 DataSource
                    private static DataSource ds ;
                
                    static{
                        try {
                            //1.加载配置文件
                            Properties pro = new Properties();
                            pro.load(JDBCUtils.class.getClassLoader().getResourceAsStream("druid.properties"));
                            //2.获取DataSource
                            ds = DruidDataSourceFactory.createDataSource(pro);
                        } catch (IOException e) {
                            e.printStackTrace();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                
                    /**
                     * 获取连接
                     */
                    public static Connection getConnection() throws SQLException {
                        return ds.getConnection();
                    }
                
                    /**
                     * 释放资源
                     */
                    public static void close(Statement stmt,Connection conn){
                       /* if(stmt != null){
                            try {
                                stmt.close();
                            } catch (SQLException e) {
                                e.printStackTrace();
                            }
                        }
                
                        if(conn != null){
                            try {
                                conn.close();//归还连接
                            } catch (SQLException e) {
                                e.printStackTrace();
                            }
                        }*/
                
                       close(null,stmt,conn);
                    }
                
                
                    public static void close(ResultSet rs , Statement stmt, Connection conn){
                
                
                        if(rs != null){
                            try {
                                rs.close();
                            } catch (SQLException e) {
                                e.printStackTrace();
                            }
                        }
                
                
                        if(stmt != null){
                            try {
                                stmt.close();
                            } catch (SQLException e) {
                                e.printStackTrace();
                            }
                        }
                
                        if(conn != null){
                            try {
                                conn.close();//归还连接
                            } catch (SQLException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                
                    /**
                     * 获取连接池方法
                     */
                
                    public static DataSource getDataSource(){
                        return  ds;
                    }
                
                }

    Spring JDBC

        * Spring框架对JDBC的简单封装。提供了一个JDBCTemplate对象简化JDBC的开发
            * 步骤:
                1. 导入jar包
                2. 创建JdbcTemplate对象。依赖于数据源DataSource
                    * JdbcTemplate template = new JdbcTemplate(ds);

                3. 调用JdbcTemplate的方法来完成CRUD的操作
                    * update():执行DML语句。增、删、改语句
                    * queryForMap():查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合
                        * 注意:这个方法查询的结果集长度只能是1
                    * queryForList():查询结果将结果集封装为list集合
                        * 注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中
                    * query():查询结果,将结果封装为JavaBean对象
                        * query的参数:RowMapper
                            * 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
                            * new BeanPropertyRowMapper<类型>(类型.class)
                    * queryForObject:查询结果,将结果封装为对象
                        * 一般用于聚合函数的查询

           * 代码:

    import cn.itcast.domain.Emp;
    				import cn.itcast.utils.JDBCUtils;
    				import org.junit.Test;
    				import org.springframework.jdbc.core.BeanPropertyRowMapper;
    				import org.springframework.jdbc.core.JdbcTemplate;
    				import org.springframework.jdbc.core.RowMapper;
    				
    				import java.sql.Date;
    				import java.sql.ResultSet;
    				import java.sql.SQLException;
    				import java.util.List;
    				import java.util.Map;
    				
    				public class JdbcTemplateDemo2 {
    				
    				    //Junit单元测试,可以让方法独立执行
    				
    				
    				    //1. 获取JDBCTemplate对象
    				    private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());
    				    /**
    				     * 1. 修改1号数据的 salary 为 10000
    				     */
    				    @Test
    				    public void test1(){
    				
    				        //2. 定义sql
    				        String sql = "update emp set salary = 10000 where id = 1001";
    				        //3. 执行sql
    				        int count = template.update(sql);
    				        System.out.println(count);
    				    }
    				
    				    /**
    				     * 2. 添加一条记录
    				     */
    				    @Test
    				    public void test2(){
    				        String sql = "insert into emp(id,ename,dept_id) values(?,?,?)";
    				        int count = template.update(sql, 1015, "郭靖", 10);
    				        System.out.println(count);
    				
    				    }
    				
    				    /**
    				     * 3.删除刚才添加的记录
    				     */
    				    @Test
    				    public void test3(){
    				        String sql = "delete from emp where id = ?";
    				        int count = template.update(sql, 1015);
    				        System.out.println(count);
    				    }
    				
    				    /**
    				     * 4.查询id为1001的记录,将其封装为Map集合
    				     * 注意:这个方法查询的结果集长度只能是1
    				     */
    				    @Test
    				    public void test4(){
    				        String sql = "select * from emp where id = ? or id = ?";
    				        Map<String, Object> map = template.queryForMap(sql, 1001,1002);
    				        System.out.println(map);
    				        //{id=1001, ename=孙悟空, job_id=4, mgr=1004, joindate=2000-12-17, salary=10000.00, bonus=null, dept_id=20}
    				
    				    }
    				
    				    /**
    				     * 5. 查询所有记录,将其封装为List
    				     */
    				    @Test
    				    public void test5(){
    				        String sql = "select * from emp";
    				        List<Map<String, Object>> list = template.queryForList(sql);
    				
    				        for (Map<String, Object> stringObjectMap : list) {
    				            System.out.println(stringObjectMap);
    				        }
    				    }
    				
    				    /**
    				     * 6. 查询所有记录,将其封装为Emp对象的List集合
    				     */
    				
    				    @Test
    				    public void test6(){
    				        String sql = "select * from emp";
    				        List<Emp> list = template.query(sql, new RowMapper<Emp>() {
    				
    				            @Override
    				            public Emp mapRow(ResultSet rs, int i) throws SQLException {
    				                Emp emp = new Emp();
    				                int id = rs.getInt("id");
    				                String ename = rs.getString("ename");
    				                int job_id = rs.getInt("job_id");
    				                int mgr = rs.getInt("mgr");
    				                Date joindate = rs.getDate("joindate");
    				                double salary = rs.getDouble("salary");
    				                double bonus = rs.getDouble("bonus");
    				                int dept_id = rs.getInt("dept_id");
    				
    				                emp.setId(id);
    				                emp.setEname(ename);
    				                emp.setJob_id(job_id);
    				                emp.setMgr(mgr);
    				                emp.setJoindate(joindate);
    				                emp.setSalary(salary);
    				                emp.setBonus(bonus);
    				                emp.setDept_id(dept_id);
    				
    				                return emp;
    				            }
    				        });
    				
    				
    				        for (Emp emp : list) {
    				            System.out.println(emp);
    				        }
    				    }
    				
    				    /**
    				     * 6. 查询所有记录,将其封装为Emp对象的List集合
    				     */
    				
    				    @Test
    				    public void test6_2(){
    				        String sql = "select * from emp";
    				        List<Emp> list = template.query(sql, new BeanPropertyRowMapper<Emp>(Emp.class));
    				        for (Emp emp : list) {
    				            System.out.println(emp);
    				        }
    				    }
    				
    				    /**
    				     * 7. 查询总记录数
    				     */
    				
    				    @Test
    				    public void test7(){
    				        String sql = "select count(id) from emp";
    				        Long total = template.queryForObject(sql, Long.class);
    				        System.out.println(total);
    				    }
    				
    				}
    

     

    展开全文
  • Tongweb5中配置JDBC连接池的文档。Web应用通过JNDI获取Tongweb配置的JDBC数据源(连接池
  • jdbc连接池实现

    万次阅读 2018-08-13 21:51:12
    jdbc连接池实现 连接池我们一直再用,比如druid、c3p0、tomcat的连接池等等,包括数据库本身也会有连接池,今天突然想研究一下数据库连接池是怎么实现的。现总结一下: 数据库连接池的目的: 减少频繁的创建/销毁...

    jdbc连接池实现

    连接池我们一直再用,比如druid、c3p0、tomcat的连接池等等,包括数据库本身也会有连接池,今天突然想研究一下数据库连接池是怎么实现的。现总结一下:

    数据库连接池的目的:

    减少频繁的创建/销毁连接,因为一次数据库连接的开销是很大的,要经过一下几个步骤:

    1.加载驱动

    2.获得一个Connection

    3.通过TCP连接数据库

    4.发送sql语句

    5.执行sql,返回结果

    6.关闭TCP连接

    7.释放Connection

    其中只有4,和5是我们需要动态操作的也是最主要的,其他操作都是重复的。

    所以如果每次都进行这一系列的操作,势必会造成不必要的系统开销,增加相应时间,所以我们可以将这些连接复用,在系统初始化的时候就建立好连接,以后直接发送sql执行就行,这样就会大大提高效率。

    比较建立一次连接和复用连接的时间:

    显然新建一次连接比复用连接更耗时,那到底复用会比新建快多少呢?我来测试一下。

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
            long start = System.currentTimeMillis();
            Class.forName(driver);
            Connection connection = DriverManager.getConnection(dbUrl, userName, password);
            String sql = "SELECT * FROM tb_user";
            PreparedStatement statement = connection.prepareStatement(sql);
            ResultSet resultSet = statement.executeQuery();
            while (resultSet.next()) {
                //省略
            }
            long end = System.currentTimeMillis();
            System.out.println("首次建立连接执行耗时:"+(end - start));
    
            start = System.currentTimeMillis();
            statement = connection.prepareStatement(sql);
            ResultSet resultSet2 = statement.executeQuery();
            while (resultSet2.next()) {
                //省略
            }
            end = System.currentTimeMillis();
            System.out.println("复用连接执行耗时:"+(end - start));
        }
    

    这段代码里首先建立了一个Connection并统计一个查询操作的耗时,然后继续使用这个连接来执行相同的查询并统计时间,输出如下:

    首次建立连接执行耗时:606
    复用连接执行耗时:1
    

    可以看到复用连接比新建连接快了600倍左右,显然性能会提高很多。

    当然以上程序并不是真正的连接池,只是在同一段代码里使用了同一个连接而已。下面据尝试建立一个连接池。

    连接池的主要功能就是实现连接的复用,说白了也就是将一些连接保存在一个集合中,当需要连接时从集合中取,释放连接时并不是真正释放,而是归还给这个集合,达到复用的目的。

    首先新建连接池类:ConnectionPool.

    为了统一接口我们实现DataSource接口.主要是实现getConnection方法。

    /**
     * Created by wxg on 2018/8/13 17:42
     */
    public class ConnectionPool implements DataSource {
        private static final String driver = "com.mysql.jdbc.Driver";
        private static final String dbUrl = "jdbc:mysql://localhost:3306/db_blog?useSSL=true";
        private static final String userName  = "root";
        private static final String password= "123456";
    
        private LinkedList<Connection> pool;
    
        private Connection getOneConnection() {
            Connection connection = null;
            try {
                Class.forName(driver);
                connection = DriverManager.getConnection(dbUrl,userName,password);
            } catch (ClassNotFoundException | SQLException e) {
                e.printStackTrace();
            }
            return connection;
        }
        @Override
        public Connection getConnection() throws SQLException {
            if(pool==null){
                pool = new LinkedList<>();
                for(int i=0;i<2;i++){
                    pool.add(getOneConnection());
                }
            }
            if(pool.size()<=0){
                pool.add(getOneConnection());
            }
            return pool.remove();
        }
        public void close(Connection connection){
            pool.add(connection);
        }
        //省略其他实现...
    }
    

    因为是使连接的获取和归还涉及到频繁的删除和添加操作,所以我们用LinkList来作为存储Connection的容器。

    这里边封装了我们常用的一次建立连接的过程到方法getOneConnection中。

    重写的getConnection中首先判断pool是否为null,若为null则初始化2个连接,然后在判断pool的size是否为0,当pool==0时说明池中没有可用连接了,所有的连接都被用了,此时就需要再调用getOneConnection来建立一个新的连接。最后是移除pool中的第一个连接并返回。

    因为这个getConnection会在没有可用连接时创建新的连接,所以这个连接池的大小取决于连接数最大时的大小,所以当系统在繁忙期间进行大量连接时,在不忙的时候就会出现大量空闲连接,我们可以作如下修改:

    if(pool.size()<=0){
         pool.add(getOneConnection());
    }
    

    改为:

    if(pool.size()<=0){
         return getOneConnection();
     }
    

    这样就相当于创建了零时连接,当然更好的做法是设置超时时间,这里就不再讨论了。

    对于close()方法很简单,但是也很重要,因为这个close并不是直接关闭掉连接,而是将连接归还给pool。实现复用。

    然后一个简单的连接池就实现啦,现在来测试一下:

    public static void main(String[] args) throws SQLException {
        ConnectionPool pool = new ConnectionPool();
        Connection connection1 = pool.getConnection();
        pool.close(connection1);
        Connection connection2 =pool.getConnection();
        pool.close(connection2);
        Connection connection3 =pool.getConnection();
        pool.close(connection3);
        Connection connection4 =pool.getConnection();
        pool.close(connection4);
        Connection connection5 =pool.getConnection();
        pool.close(connection5);
    }
    

    然后执行调试,结果如下:

    其中红色框是Connection对象,可以看到前几个都是888和889,也就是复用了初始化的两个连接,但是获取最后一个连接的时候因为在它之前已经有两个连接被获取了,池为空了,所以就再新建了一个连接对象,所以是890了。

    绿色框是执行时间,可以看到第一次初始化连接时用了625毫秒,而后面复用连接用了0毫秒,最后一次新建连接用了7毫秒,因为省去了加载驱动等过程,所以会比第一次快。

    通过这个测试可以发现连接池的作用是多么的重要,它能使数据库连接性能提升几百倍!

    然后我们这里存在一个问题就是我们的连接对象是Connection对象,它包含了close()方法来释放连接,我们一般也是调用此方法来释放连接,而不是调用连接池的,因此,我们要保证嗲用的是我们自己的close()方法,因为我们的close方法并不会真的释放掉连接而是让它回归到连接池中,所以就要实现Connection来重写close。

    只需要重写close()方法即可:

    class MyConnection implements Connection {
        private Connection connection;
    
        MyConnection(Connection connection) {
            this.connection = connection;
        }
    
        @Override
        public void close() throws SQLException {
            pool.add(connection);
        }
    //...省略其他方法
    }
    

    这里使用装饰器模式将Connection包装成MyConnection,并覆盖了close方法,在close时将Connection归还到pool。

    测试如下:

    结果与上一步测试类似。(返回的MyConncection不同是因为返回时new了Myconnection进行包装,否则将无法调用我们自己写的lclose()方法)。

    结束!

    展开全文
  • jdbc连接池原理

    2015-09-23 23:18:21
    关于jdbc连接池连接数据库的原理
  • JDBC连接池的九种查询

    千次阅读 2021-03-09 20:04:14
    package JDBC_Demo;import java.sql.SQLException;import java.util.List;import java.util.Map;import org.apache.commons.dbutils.DbUtils;import org.apache.commons.dbutils.QueryRunner;import org.apache.comm...
  • Tongweb中配置JDBC连接池
  • C3P0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection 和Statement 池的DataSources 对象 DBCP (Database Connection Pool)是一个依赖Jakarta ...
  • JDBC - Java 连接Mysql JDBC连接池使用工具 C3P0 连接池 and druid-1.0.9
  • 使用PostgreSQL JDBC连接池

    千次阅读 2020-12-20 06:52:18
    使用org.postgresql.ds.PGPoolingDataSource这是一个例子:...然而在这个链接的文档中,由于它的局限性,他们不鼓励使用postgreSQL数据源:The pooling data-source impl...
  • JDBC连接池&DBUtils1

    2022-08-08 22:49:45
    JDBC连接池&DBUtils1
  • JDBC链接的一些见解和实例
  • JDBC连接池原理及分析

    万次阅读 多人点赞 2018-09-10 10:27:18
    今天给大家分享一下,修真院官网Java任务1,深度思考中的知识点JDBC连接池原理 一、.背景介绍 什么是连接池 1)连接池,首先从字面意思理解,这是一个偏正短语,左偏右正,重点在池这个字上。 池(Pool)技术在一定...
  • jdbc 连接池

    万次阅读 2017-08-12 13:35:43
    1. 连接池 思考: 程序中连接如何管理? 1. 连接资源宝贵;需要对连接管理 2. 连接: a) 操作数据库,创建连接 b) 操作结束, 关闭! 分析: 涉及频繁的连接的打开、关闭,影响程序的运行效率! 连接管理: ...
  • SpringBoot整合Mybatis与JDBC连接池

    千次阅读 2020-04-30 11:43:00
    SpringBoot整合Mybatis与JDBC连接池 整合连接池 jdbc连接池是spring配置中的重要一环,在SpringBoot中该如何处理呢? 答案是不需要处理,我们只要找到SpringBoot提供的启动器即可: 在pom.xml中引入jdbc的启动器: &...
  • JDBC 连接池参数

    千次阅读 2019-03-25 14:40:01
    JDBC连接池参数: jdbc.initialSize=0 //初始化连接 jdbc.maxActive=30 //连接池的最大数据库连接数,设为0表示无限制 jdbc.maxIdle=20 //没有人用连接的时候,最大闲置的连接个数,设置为0时,表示没有限制。 jdbc....
  • NULL 博文链接:https://coolxing.iteye.com/blog/1258983
  • JAVA——JDBC连接池的基本原理及实现方式

    万次阅读 多人点赞 2017-12-29 15:32:00
    使用数据库连接池的原因:传统方式创建和销毁连接都需要消耗系统资源 传统方式创建和销毁连接都需要消耗时间使用数据库连接池的目的:为了复用连接,代替传统的频繁占用系统资源和耗费时间的方式 便于管理连接,可以...
  • jdbc连接池c3p0工具包

    2018-01-22 21:46:06
    java使用jdbc连接池时所使用的c3p0工具包,也可在官网下载
  • JDBC连接池[归类].pdf

    2021-10-19 15:14:42
    JDBC连接池[归类].pdf

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 203,540
精华内容 81,416
关键字:

jdbc连接池

友情链接: MAX.zip