博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据库连接池
阅读量:7030 次
发布时间:2019-06-28

本文共 9392 字,大约阅读时间需要 31 分钟。

1、什么是数据库连接池

传统的开发模式下,Servlet处理用户的请求,找Dao查询数据,dao会创建与数据库之间的链接,完成数据查询后会关闭数据库的链接。

这样的方式会导致用户每次请求都要向数据库建立链接而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长。假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大的浪费数据库的资源,并且极易造成数据库服务器内存溢出、宕机。

解决方案: 就是数据库连接池

连接池就是数据库连接对象的一个缓冲池.

用池来管理Connection,这可以重复使用Connection。有了池,所以我们就不用自己来创建Connection,而是通过池来获取Connection对象。当使用完Connection后,

调用Connection的close()方法也不会真的关闭Connection,而是把Connection“归还”给池。池就可以再利用这个Connection对象了。

 

池参数(所有池参数都有默认值)

初始大小:10个

最小空闲连接数:3个

增量:一次创建的最小单位(5个)

最大空闲连接数:12个

最大连接数:20个

最大的等待时间:1000毫秒

 

四大连接参数

连接池也是使用四大连接参数来完成创建连接对象!

 

实现的接口

连接池必须实现:javax.sql.DataSource接口!

连接池返回的Connection对象,它的close()方法与众不同!调用它的close()不是关闭,而是把连接归还给池!

 

2、jdbc数据库连接池接口(DataSource)

Java为数据库连接池提供了公共的接口:javax.sql.DataSource,各个厂商可以让自己的连接池实现这个接口。这样应用程序可以方便的切换不同厂商的连接池!

 

3、自定义连接池

   

如何对Connection对象,生成一个代理对象:

|--Proxy

         static Object newProxyInstance(

      ClassLoader loader,    当前使用的类加载器

      Class<?>[] interfaces,   目标对象(Connection)实现的接口类型

      InvocationHandler h    事件处理器:当执行上面接口中的方法的时候,就会自动触发事件处理器代码,把当前执行的方法(method)作为参数传入。

/** * 自定义连接池, 管理连接 * 代码实现:    1.  MyPool.java  连接池类,       2.  指定全局参数:  初始化数目、最大连接数、当前连接、   连接池集合    3.  构造函数:循环创建3个连接    4.  写一个创建连接的方法    5.  获取连接    ------>  判断: 池中有连接, 直接拿     ------>                池中没有连接,    ------>                 判断,是否达到最大连接数; 达到,抛出异常;没有达到最大连接数,            创建新的连接    6. 释放连接     ------->  连接放回集合中(..) * */public class MyPool {    private int init_count = 3;        // 初始化连接数目    private int max_count = 6;        // 最大连接数    private int current_count = 0;  // 记录当前使用连接数    // 连接池 (存放所有的初始化连接)    private LinkedList
pool = new LinkedList
(); //1. 构造函数中,初始化连接放入连接池 public MyPool() { // 初始化连接 for (int i=0; i
0){ return pool.removeFirst(); } // 3.2 连接池中没有连接: 判断,如果没有达到最大连接数,创建; if (current_count < max_count) { // 记录当前使用的连接数 current_count++; // 创建连接 return createConnection(); } // 3.3 如果当前已经达到最大连接数,抛出异常 throw new RuntimeException("当前连接已经达到最大连接数目 !"); } //4. 释放连接 public void realeaseConnection(Connection con) { // 4.1 判断: 池的数目如果小于初始化连接,就放入池中 if (pool.size() < init_count){ pool.addLast(con); } else { try { // 4.2 关闭 current_count--; con.close(); } catch (SQLException e) { throw new RuntimeException(e); } } } public static void main(String[] args) throws SQLException { MyPool pool = new MyPool(); System.out.println("当前连接: " + pool.current_count); // 3 // 使用连接 pool.getConnection(); pool.getConnection(); Connection con4 = pool.getConnection(); Connection con3 = pool.getConnection(); Connection con2 = pool.getConnection(); Connection con1 = pool.getConnection(); // 释放连接, 连接放回连接池// pool.realeaseConnection(con1); /* * 希望:当关闭连接的时候,要把连接放入连接池!【当调用Connection接口的close方法时候,希望触发pool.addLast(con);操作】 * 把连接放入连接池 * 解决1:实现Connection接口,重写close方法 * 解决2:动态代理 */ con1.close(); // 再获取 pool.getConnection(); System.out.println("连接池:" + pool.pool.size()); // 0 System.out.println("当前连接: " + pool.current_count); // 3 } }

 

 

 

 DBCP连接池:

   DBCP 是 Apache 软件基金组织下的开源连接池实现,使用DBCP数据源,应用程序应在系统中增加如下两个 jar 文件:

    •    Commons-dbcp.jar:连接池的实现

    •    Commons-pool.jar:连接池实现的依赖库

   Tomcat 的连接池正是采用该连接池来实现的。该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用。

    l  核心类:BasicDataSource

    l  使用步骤

    •    引入jar文件

      l  commons-dbcp-1.4.jar

      l  commons-pool-1.5.6.jar

public class App_DBCP {    // 1. 硬编码方式实现连接池    @Test    public void testDbcp() throws Exception {        // DBCP连接池核心类        BasicDataSource dataSouce = new BasicDataSource();        // 连接池参数配置:初始化连接数、最大连接数 / 连接字符串、驱动、用户、密码        dataSouce.setUrl("jdbc:mysql:///jdbc_demo");            //数据库连接字符串        dataSouce.setDriverClassName("com.mysql.jdbc.Driver");  //数据库驱动        dataSouce.setUsername("root");                            //数据库连接用户        dataSouce.setPassword("root");                             //数据库连接密码        dataSouce.setInitialSize(3);  // 初始化连接        dataSouce.setMaxActive(6);      // 最大连接        dataSouce.setMaxIdle(3000);   // 最大空闲时间                // 获取连接        Connection con = dataSouce.getConnection();        con.prepareStatement("delete from admin where id=3").executeUpdate();        // 关闭        con.close();    }        @Test    // 2. 【推荐】配置方式实现连接池  ,  便于维护    public void testProp() throws Exception {        // 加载prop配置文件        Properties prop = new Properties();        // 获取文件流        InputStream inStream = App_DBCP.class.getResourceAsStream("db.properties");        // 加载属性配置文件        prop.load(inStream);        // 根据prop配置,直接创建数据源对象        DataSource dataSouce = BasicDataSourceFactory.createDataSource(prop);                // 获取连接        Connection con = dataSouce.getConnection();        con.prepareStatement("delete from admin where id=4").executeUpdate();        // 关闭        con.close();    }}

 

配置方式实现DBCP连接池,  配置文件中的key与BaseDataSouce中的属性一样:

 

#基本配置driverClassName=com.mysql.jdbc.Driverurl=jdbc:mysql://localhost:3306/mydb1username=rootpassword=123#初始化池大小,即一开始池中就会有10个连接对象默认值为0initialSize=0#最大连接数,如果设置maxActive=50时,池中最多可以有50个连接,当然这50个连接中包含被使用的和没被使用的(空闲)#你是一个包工头,你一共有50个工人,但这50个工人有的当前正在工作,有的正在空闲#默认值为8,如果设置为非正数,表示没有限制!即无限大maxActive=8#最大空闲连接#当设置maxIdle=30时,你是包工头,你允许最多有20个工人空闲,如果现在有30个空闲工人,那么要开除10个#默认值为8,如果设置为负数,表示没有限制!即无限大maxIdle=8#最小空闲连接#如果设置minIdel=5时,如果你的工人只有3个空闲,那么你需要再去招2个回来,保证有5个空闲工人#默认值为0minIdle=0#最大等待时间#当设置maxWait=5000时,现在你的工作都出去工作了,又来了一个工作,需要一个工人。#这时就要等待有工人回来,如果等待5000毫秒还没回来,那就抛出异常#没有工人的原因:最多工人数为50,已经有50个工人了,不能再招了,但50人都出去工作了。#默认值为-1,表示无限期等待,不会抛出异常。maxWait=-1#连接属性#就是原来放在url后面的参数,可以使用connectionProperties来指定#如果已经在url后面指定了,那么就不用在这里指定了。#useServerPrepStmts=true,MySQL开启预编译功能#cachePrepStmts=true,MySQL开启缓存PreparedStatement功能,#prepStmtCacheSize=50,缓存PreparedStatement的上限#prepStmtCacheSqlLimit=300,当SQL模板长度大于300时,就不再缓存它connectionProperties=useUnicode=true;characterEncoding=UTF8;useServerPrepStmts=true;cachePrepStmts=true;prepStmtCacheSize=50;prepStmtCacheSqlLimit=300#连接的默认提交方式#默认值为truedefaultAutoCommit=true#连接是否为只读连接#Connection有一对方法:setReadOnly(boolean)和isReadOnly()#如果是只读连接,那么你只能用这个连接来做查询#指定连接为只读是为了优化!这个优化与并发事务相关!#如果两个并发事务,对同一行记录做增、删、改操作,是不是一定要隔离它们啊?#如果两个并发事务,对同一行记录只做查询操作,那么是不是就不用隔离它们了?#如果没有指定这个属性值,那么是否为只读连接,这就由驱动自己来决定了。即Connection的实现类自己来决定!defaultReadOnly=false#指定事务的事务隔离级别#可选值:NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE#如果没有指定,那么由驱动中的Connection实现类自己来决定defaultTransactionIsolation=REPEATABLE_READ

 

  

  C3P0连接池:

 

  C3P0连接池:

 

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

 

  C3P0连接池,核心类:

 

           CombopooledDataSource ds;

 

  使用:

 

    1.       下载,引入jar文件:  c3p0-0.9.1.2.jar

 

    2.       使用连接池,创建连接

 

      a)         硬编码方式

 

      b)        配置方式(xml)

            配置文件要求:

              l  文件名称:必须叫c3p0-config.xml

              l  文件位置:必须在src下

        c3p0也可以指定配置文件,而且配置文件可以是properties,也可以  xml的。当然xml的高级一些了。但是c3p0的配置文件名必须为c3p0-config.xml,并且必须放在类路径下。

下面是源码

jdbc:mysql://localhost:3306/mydb1
com.mysql.jdbc.Driver
root
123
3
10
2
10
jdbc:mysql://localhost:3306/mydb1
com.mysql.jdbc.Driver
root
123
3
10
2
10

 

public class App {    @Test    //1. 硬编码方式,使用C3P0连接池管理连接    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(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连接池核心工具类        // 自动加载src下c3p0的配置文件【c3p0-config.xml】        ComboPooledDataSource dataSource = new ComboPooledDataSource();// 使用默认的配置                // 获取连接        Connection con = dataSource.getConnection();        // 执行更新        con.prepareStatement("delete from admin where id=5").executeUpdate();        // 关闭        con.close();             }   //获取配置文件中“orcale-cofig"的配置信息   

  public void fun2() throws PropertyVetoException, SQLException {

 

       ComboPooledDataSource ds = new ComboPooledDataSource("orcale-config");

 

       Connection con = ds.getConnection();

 

       System.out.println(con);

 

       con.close();

    } }

 

转载于:https://www.cnblogs.com/flei/p/6728303.html

你可能感兴趣的文章
洛谷 P1048 采药
查看>>
Java反射 : Declared的作用 ( 例如 : getMethods和getDeclaredMethods )
查看>>
Feign性能优化注意事项--超时
查看>>
httpd的简单配置(转)
查看>>
yum简介(转)
查看>>
架构漫谈(一):什么是架构?(转)
查看>>
Socket 专题
查看>>
DNS安全浅议、域名A记录(ANAME),MX记录,CNAME记录 专题
查看>>
codeforces 877E Danil and a Part-time Job
查看>>
svn服务器时间与本地时间不同步解决
查看>>
postgres10.2时区研究
查看>>
ie9以下不支持html5 解决方法
查看>>
JAVA异常体系
查看>>
C#'~'按位取反运算符的使用
查看>>
HTTP协议
查看>>
防止SQL注入
查看>>
java.io几种读写文件的方式
查看>>
jquery 点击查看,收起特效
查看>>
JS自学笔记05
查看>>
SQL Server参数化查询中应用Like
查看>>