数据库连接池
Posted South.return
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据库连接池相关的知识,希望对你有一定的参考价值。
目录
DAO及相关实现类
概述:Data Access Object访问数据信息的类和接口,包括了对数据的CRUD(Create、Retrival、Update、Delete),而不包含任何业务相关的信息。有时也称作:BaseDAO。
作用:为了实现功能的模块化,更有利于代码的维护和升级。
DAO使用的体现:
层次结构 代码实现:
父类 接口 具体实现类
数据库连接池
开发基于数据库程序时的传统模式 1. 在主程序(如servlet、beans)中建立数据库连接
2. 进行sql操作
3. 断开数据库连接存在的问题 1. 数据库的连接资源并没有得到很好的重复利用
2. 对于每一次数据库连接,使用完后都得断开
3. 这种开发不能控制被创建的连接对象数
基本思想 为数据库连接建立一个"缓冲池"。预先在缓冲池中放入一定数量的连接,当需要建立数据库连接时,只需从"缓冲池"中取出一个,使用完毕之后再放回去 数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是重新建立一个 连接池最小数据库连接数 数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中。无论这些数据库连接是否被使用,连接池都将一直保证至少拥有这么多的连接数量
连接池最大数据库连接数 限定了这个连接池能占有的最大连接数,当应用程序向连接池请求的连接数超过最大连接数量时,这些请求将被加入到等待队列中 工作原理
优点 资源重用 由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销
在减少系统消耗的基础上,另一方面也增加了系统运行环境的平稳性
更快的系统反应速度 数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用
此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接
避免了数据库连接初始化和释放过程的时间开销,从而减少了系统的响应时间
新的资源分配手段 对于多应用共享同一数据库的系统而言,可在应用层通过数据库连接池的配置
实现某一应用最大可用数据库连接数的限制,避免某一应用独占所有的数据库资源
统一的连接管理
避免数据库连接泄漏
在较为完善的数据库连接池实现中,可根据预先的占用超时设定
强制回收被占用连接,从而避免了常规数据库连接操作中可能出现的资源泄露
分类 概述:JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由服务器
(Weblogic, WebSphere, Tomcat)提供实现,也有一些开源组织提供实现
DBCP 说明:Apache提供的数据库连接池,tomcat服务器自带dbcp数据库连接池
速度相对c3p0较快,但因自身存在BUG,Hibernate3已不再提供支持
该连接池依赖该组织下的另一个开源系统:Common-pool。如需
使用该连接池实现,应在系统中增加如下两个 jar 文件:
- Commons-dbcp.jar:连接池的实现
- Commons-pool.jar:连接池实现的依赖库Tomcat的连接池正是采用该连接池来实现的
该数据库连接池既可以与应用服务器整合使用,也可由应用程序独立使用
配置属性:
C3P0
说明:一个开源组织提供的一个数据库连接池,速度相对较慢,稳定性还可以。hibernate官方推荐使用 Proxool 说明:sourceforge下的一个开源项目数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点 BoneCP 说明:一个开源组织提供的数据库连接池,速度快 Druid(德鲁伊) 说明:阿里提供的数据库连接池,据说是集DBCP 、C3P0 、Proxool优点于一身的数据库连接池,
同时加入了日志监控,可以很好的监控DB池连接和SQL的执行情况,可以说是针对监控而生的DB
连接池,是目前最好的连接池之一
配置参数:
表格中的链接:https://github.com/alibaba/druid/wiki/%E4%BD%BF%E7%94%A8ConfigFilter
说明 DataSource通常被称为数据源,它包含连接池和连接池管理两个部分
习惯上也经常把DataSource称为连接池
DataSource用来取代DriverManager来获取Connection,获取速度快
同时可以大幅度提高数据库访问速度
注意 在使用任意一种连接池时都要先进行导jar包 数据源和数据库连接不同,数据源无需创建多个,它是产生数据库连接的工厂,因此整个应用只需要一个数据源即可 当数据库访问结束后,程序还是像以前一样关闭数据库连接:conn.close(); 但conn.close()并没有关闭数据库的物理连接
它仅仅把数据库连接释放,归还给了数据库连接池
代码实现:Druid(德鲁伊)数据库连接池
src下的配置文件:druid.properties
url=jdbc:mysql:///test username=root password=root driverClassName=com.mysql.jdbc.Driver initialSize=10 maxActive=10
@Test public void getConnection() throws Exception { Properties pros = new Properties(); InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("druid.properties"); pros.load(is); DataSource source = DruidDataSourceFactory.createDataSource(pros); Connection conn = source.getConnection(); System.out.println(conn); }
Apache-DBUtils实现CRUD
简介:Apache组织提供的一个开源JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
API介绍:
- org.apache.commons.dbutils.QueryRunner
- org.apache.commons.dbutils.ResultSetHandler
- 工具类:org.apache.commons.dbutils.DbUtils
API包说明:
API的使用:
DbUtils 概述:提供如关闭连接、装载JDBC驱动程序等常规工作的工具类,里面的所有方法都是静态的 主要方法 public static void close(…) throws java.sql.SQLException 说明:DbUtils类提供了三个重载的关闭方法
这些方法检查所提供的参数是不是NULL
如果不是的话,它们就关闭Connection、Statement和ResultSet
public static void closeQuietly(…) 说明:这一类方法不仅能在Connection、Statement和ResultSet
为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLEeception
public static void commitAndClose(Connection conn)throws SQLException 说明:用来提交连接的事务,然后关闭连接 public static void rollback(Connection conn)throws SQLException 说明:允许conn为null,因为方法内部做了判断 public static boolean loadDriver(java.lang.String driverClassName) 说明:这一方装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException public static void commitAndCloseQuietly(Connection conn) 说明:用来提交连接,然后关闭连接,并且在关闭连接时不抛出SQL异常
QueryRunner 概述:该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量 两个构造器 - 默认的构造器
- 需要一个 javax.sql.DataSource 来作参数的构造器主要方法 更新 public int update(Connection conn, String sql, Object... params) throws SQLException
用来执行一个更新(插入、更新或删除)操作
插入 public <T> T insert(Connection conn,String sql,ResultSetHandler<T> rsh, Object... params)
throws SQLException:只支持INSERT语句
批处理 public int[] batch(Connection conn,String sql,Object[][] params)throws SQLException
支持INSERT, UPDATE, or DELETE语句
public <T> T insertBatch(Connection conn,String sql,ResultSetHandler<T> rsh,Object[][]
params)throws SQLException:只支持INSERT语句
查询 public Object query(Connection conn, String sql, ResultSetHandler rsh,Object... params)
throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来
作为查询语句的置换参数。该方法会自行处理 PreparedStatement和ResultSet的创建和关闭
ResultSetHandler接口 概述:该接口用于处理java.sql.ResultSet,将数据按要求转换为另一种形式
ResultSetHandler接口提供了一个单独的方法:Object handle (java.sql.ResultSet .rs)
主要实现类 ArrayHandler:把结果集中的第一行数据转成对象数组
ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中
BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中
BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中
存放到List里
ScalarHandler:查询单个值对象
ColumnListHandler:将结果集中某一列的数据存放到List中
KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里
再把这些map再存到一个map里,其key为指定的key
MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值
MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List
代码实现:
//测试插入 @Test public void testInsert() { Connection conn = null; try { QueryRunner runner = new QueryRunner(); conn = JDBCUtils.getConnection3(); String sql = "insert into customers(name,email,birth)values(?,?,?)"; int insertCount = runner.update(conn, sql, "蔡徐坤", "caixukun@126.com", "1997-09-08"); System.out.println("添加了"+insertCount+"条记录"); }catch (Exception e){ e.printStackTrace(); }finally { JDBCUtils.closeResource(conn,null); } } //测试查询 //BeanHander:是ResultSetHandler接口的实现类,用于封装表中的一条记录 @Test public void testQuery() { Connection conn = null; try { QueryRunner runner = new QueryRunner(); conn = JDBCUtils.getConnection3(); String sql = "select id,name,email,birth from customers where id=?"; BeanHandler<Customer> handler = new BeanHandler<>(Customer.class); Customer customer = runner.query(conn, sql, handler, 10); System.out.println(customer); }catch (Exception e){ e.printStackTrace(); }finally { JDBCUtils.closeResource(conn,null); } } //BeanListHandler:是ResultSetHandler接口的实现类,用于封装表中的多条记录构成的集合 @Test public void testQuery2() { Connection conn = null; try { QueryRunner runner = new QueryRunner(); conn = JDBCUtils.getConnection3(); String sql = "select id,name,email,birth from customers where id<?"; BeanListHandler<Customer> handler = new BeanListHandler<>(Customer.class); List<Customer> list = runner.query(conn, sql, handler, 10); list.forEach(System.out::println); }catch (Exception e){ e.printStackTrace(); }finally { JDBCUtils.closeResource(conn,null); } } //ScalarHandler:用于查询特殊值 @Test public void testQuery5() { Connection conn = null; try { QueryRunner runner = new QueryRunner(); conn = JDBCUtils.getConnection3(); String sql = "select count(*) from customers"; ScalarHandler handler = new ScalarHandler(); Long count = (Long) runner.query(conn, sql, handler); System.out.println(count); }catch (Exception e){ e.printStackTrace(); }finally { JDBCUtils.closeResource(conn,null); } }
以上是关于数据库连接池的主要内容,如果未能解决你的问题,请参考以下文章
newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段
连接池报错 Proxool Provider unable to load JAXP configurator file: proxool.xml
MySQL与Redis数据库连接池介绍(图示+源码+代码演示)