一、数据库连接池

1. 什么是连接池

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

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

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

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

我们可以先创建10个数据库连接缓存在连接池中,当用户有请求过来的时候,dao不必创建数据库连接,而是从数据库连接池中获取一个,用完了也不必关闭连接,而是将连接换回池子当中,继续缓存

使用数据库连接池可以极大地提高系统的性能

2. 实现数据库连接池

jdbc统一了数据库的操作  定义了规范

jdbc针对数据库连接池也定义的接口java.sql.DataSource,所有的数据库连接池实现都要实现该接口

该接口中定义了两个重载的方法

Connection getConnection()

Connection getConnection(String username,String password)

数据库连接池实现思路

1)定义一个类实现java.sql.DataSource接口

2)定义一个集合用于保存Connection对象,由于频繁地增删操作,用LinkedList比较好

3)实现getConnection方法,在方法中取出LinkedList集合中的一个连接对象返回

注意:

返回的Connection对象不是从集合中获得,而是删除

用户用完Connection,会调用close方法释放资源,此时要保证连接换回连接池,而不是关闭连接

重写close方法是难点,解决方案:装饰设计模式、动态代理

二、 数据源

通常我们把DataSource的实现,按其英文含义称之为数据源,数据源中都包含了数据库连接池的实现。

一些开源组织提供了数据源的独立实现,常用的有:

DBCP 数据库连接池

C3P0 数据库连接池

1.  DBCP 数据源

介绍

DBCP 是 Apache 软件基金组织下的开源连接池实现

tomcat服务器就是使用DBCP作为数据库连接池

使用DBCP数据源,需要导入两个jar包

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

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

DBCP核心 API

BasicDataSource

数据源实现

BasicDataSourceFactory

用于创建数据源的工厂类

dbcp 创建连接池

方法1: 直接创建对象,设置参数

BasicDataSource bds = new BasicDataSource();

// 设置连接数据库需要的配置信息

bds.setDriverClassName("com.mysql.jdbc.Driver");

bds.setUrl("jdbc:mysql://localhost:3306/jdbc3");

bds.setUsername("root");

bds.setPassword("root");

// 设置连接池的参数

bds.setInitialSize(5);

bds.setMaxActive(10);

ds = bds

方法2: 通过工厂类创建对象,读取配置文件

try {

Properties prop =new Properties();

// 读配置文件

InputStream in =

JdbcUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties");

prop.load(in);

ds =BasicDataSourceFactory.createDataSource(prop);

}catch (Exception e) {

throw newExceptionInInitializerError(e);

}

配置文件为dbcpconfig.properties

#连接设置

driverClassName=com.mysql.jdbc.Driver

url=jdbc:mysql://localhost:3306/jdbc3

username=root

password=root

#<!-- 初始化连接 -->

initialSize=5

#最大连接数量

maxActive=10

#<!-- 最大空闲连接 -->

maxIdle=10

#<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 -->

maxWait=60000

#JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;]

#注意:"user" 与"password" 两个属性会被明确地传递,因此这里不需要包含他们。

connectionProperties=useUnicode=true;characterEncoding=gbk

#指定由连接池所创建的连接的自动提交(auto-commit)状态。

defaultAutoCommit=true

#driver default 指定由连接池所创建的连接的只读(read-only)状态。

#如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix)

defaultReadOnly=

#driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。

#可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED,REPEATABLE_READ, SERIALIZABLE

defaultTransactionIsolation=READ_UNCOMMITTED

2.  C3P0 数据源

介绍

c3p0是一个开源的jdbc连接池,我们熟悉的Hibernate和 Sprint 框架使用的都是该数据源

创建连接池对象

方法1:直接创建对象,设置参数

ComboPooledDataSource cpds = new ComboPooledDataSource();

cpds.setDriverClass("com.mysql.jdbc.Driver");

cpds.setJdbcUrl("jdbc:mysql://localhost:3306/jdbc3");

cpds.setUser("root");

cpds.setPassword("root");

cpds.setInitialPoolSize(5);

cpds.setMaxPoolSize(15);

方法2:读取配置文件

ComboPooledDataSource cpds = newComboPooledDataSource("itcast");

配置文件为c3p0-config.xml 该文件需要放在类路径下

<c3p0-config>

<default-config>

<!—- 默认配置 –->

<propertyname="initialPoolSize">5</property>

<propertyname="maxPoolSize">15</property>

<propertyname="driverClass">com.mysql.jdbc.Driver</property>

<propertyname="jdbcUrl">jdbc:mysql://localhost:3306/jdbc3</property>

<propertyname="user">root</property>

<propertyname="password">root</property>

</default-config>

<named-configname="xwh">

<propertyname="initialPoolSize">5</property>

<propertyname="maxPoolSize">15</property>

<propertyname="driverClass">com.mysql.jdbc.Driver</property>

<propertyname="jdbcUrl">jdbc:mysql://localhost:3306/jdbc3</property>

<propertyname="user">root</property>

<propertyname="password">root</property>

</named-config>

</c3p0-config>

三、ResultSetMetaData对象

元数据,可以理解为描述数据的数据

jdbc中的元数据是指数据库、表、列的定义信息

ResultSetMetaData对象表示结果集 ResultSet对象的元数据

获得该对象:

ResultSetMetaDatametaData = rs.getMetaData();

常用方法:

getColumnCount()  返回resultset对象的列数

getColumnName(int column)  获得指定列的名称

getColumnTypeName(int column) 获得指定列的类型

四、jdbc优化

使用jdbc对数据库进行crud操作时,会有很多重复的代码,仔细分析不难发现其实变化的只是其中几行代码

对于 cud(增删改) 操作,代码几乎完全一样, 唯一的区别就是sql语句不同,我们完全可以把相同的代码抽取出来定义在一个工具方法中,然后定义一个参数来接收sql语句

对于 r(查询) 操作,除SQL语句不同之外,根据操作的实体不同,对ResultSet结果集的处理也有所不相同,因此可义一个query方法,除以参数形式接收变化的SQL语句外,可以使用策略模式由qurey方法的调用者决定如何把ResultSet中的数据映射到实体对象中

优化后的工具类 JdbcUtils

// 通用的增删改方法

public static int update(String sql, Object[] params) throws SQLException {

Connection conn =null;

PreparedStatementpstmt = null;

ResultSet rs = null;

try {

// 获得连接

conn =getConnection();

// 预编译sql

pstmt =conn.prepareStatement(sql);

// 将参数设置进去

for(int i=0; params!=null&&i<params.length; i++) {

pstmt.setObject(i+1,params[i]);

}

// 发送sql

int num = pstmt.executeUpdate();

return num;

} finally {

// 释放资源

release(conn,pstmt, rs);

}

}

// 优化查询

public static Object query(String sql, Object[] params,ResultSetHandler rsh) throws SQLException {

Connection conn =null;

PreparedStatementpstmt = null;

ResultSet rs = null;

try {

// 获得连接

conn =getConnection();

// 预编译sql

pstmt =conn.prepareStatement(sql);

// 将参数设置进去

for(int i=0; params!=null&&i<params.length;i++) {

pstmt.setObject(i+1,params[i]);

}

// 发送sql

rs =pstmt.executeQuery();

// 不知道别人想如何处理结果集

// 干脆想别人所要一个结果集的处理器

// 为了让当前代码继续,定义一个结果集处理器接口

// 策略模式,规定算法,具体的算法留给将来的调用者实现

Object obj =rsh.handle(rs);

return obj;

} finally {

// 释放资源

release(conn,pstmt, rs);

}

}

结果集处理器接口

public interface ResultSetHandler {

// 处理结果集的方法

public Objecthandle(ResultSet rs);

}

实现类:

BeanListHandler

public class BeanListHandler implements ResultSetHandler{

private Classclazz;

publicBeanListHandler(Class clazz) {

this.clazz =clazz;

}

public Objecthandle(ResultSet rs) {

try {

// 取出结果集所有的记录,封装到bean,存入list返回

List list= new ArrayList();

while(rs.next()) {

Objectbean = clazz.newInstance();

// 获得元数据

ResultSetMetaDatametaData = rs.getMetaData();

// 获得列的数量

intcount = metaData.getColumnCount();

// 遍历列

for(inti=1; i<=count; i++) {

// 取列名

StringcolumnName = metaData.getColumnName(i);

// 取这列的值

Objectvalue = rs.getObject(columnName);

// 反射出属性

Fieldfield = clazz.getDeclaredField(columnName);

// 设置属性

field.setAccessible(true);

field.set(bean,value);

}

// 加入list

list.add(bean);

}

returnlist;

} catch(Exception e) {

throw newRuntimeException(e);

}

}

}

BeanHandler

public class BeanHandler implements ResultSetHandler {

private Classclazz;

publicBeanHandler(Class clazz) {

this.clazz =clazz;

}

public Objecthandle(ResultSet rs) {

// 不知道有几列数据,不知道列名,不知道封装到什么样的bean

// 表的列明和javabean的字段名一致

try {

if(rs.next()){

// 创建bean

Objectbean = clazz.newInstance();

// 封装数据

// 获得结果集的元数据

ResultSetMetaDatametaData = rs.getMetaData();

intcount = metaData.getColumnCount();

// 迭代取每一列的数据

for(inti=1; i<=count; i++) {

// 获得列名  username

StringcolumnName = metaData.getColumnName(i);

// 获得数据ddd

Objectvalue = rs.getObject(columnName);

// 根据列名反射出映射的属性 username

Fieldfield = clazz.getDeclaredField(columnName);

// 为属性赋值

field.setAccessible(true);

field.set(bean,value);

}

returnbean;

}

return null;

} catch(Exception e) {

throw newRuntimeException(e);

}

}

}

ArrayHandler

// 取出第一行的所有记录存入一个Object数组

public class ArrayHandler implements ResultSetHandler {

public Objecthandle(ResultSet rs) {

try {

if(rs.next()) {

// 指向了第一行的记录

// 获得元数据

ResultSetMetaDatametaData = rs.getMetaData();

// 获得列数

intcount = metaData.getColumnCount();

// 创建数组

Object[]arr = new Object[count];

// 迭代所有列的值,存入数组

for(inti=1; i<=count; i++) {

Objectvalue = rs.getObject(i); // 获得指定列的值

arr[i-1]= value;

}

returnarr;

}

return null;

} catch(Exception e) {

throw newRuntimeException(e);

}

}

}

批处理

处理大数据

Clob Character large Object

text

Blob binary large object

数据库连接池 DBCP和c3p0数据库连接池相关推荐

  1. 常用数据库连接池 (DBCP、c3p0、Druid) 配置说明

    转载自  常用数据库连接池 (DBCP.c3p0.Druid) 配置说明 1. 引言 1.1 定义 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出.对数据库连接的 ...

  2. 数据库连接池 (DBCP、c3p0、Druid) 配置说明和对比

    1. 引言 1.1 定义 数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出. 对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标.数据 ...

  3. 数据库连接池种类、C3P0数据库连接池、德鲁伊数据库连接池

    数据库连接池种类 1.JDBC的数据库连接池使用javax.sql.DataSource来表示,DataSource只是一个接口,该接口通常由第三方提供实现 2.C3P0数据库连接池,速度相对较慢,稳 ...

  4. 连接池dbcp跟c3p0

    使用连接池的目的:重复利用Connection资源 连接池概述: 在Java中,我们使用javax.sql.DataSource来表示连接池对象.DataSource:数据源,其实就是连接池,Conn ...

  5. JavaWeb基础—数据库连接池DBCP、C3P0

    一.基本概念 数据库连接池负责分配.管理和释放数据库连接 数据库连接池:(池用map来实现居多) 用处:为了可重用(销毁创建麻烦,开销大)(招培训老师的例子) 二.编写实现数据库连接池 池参数: 初识 ...

  6. javaweb mysql 连接池 c3p0 配置_JavaWeb基础—数据库连接池DBCP、C3P0

    一.基本概念 数据库连接池负责分配.管理和释放数据库连接 数据库连接池:(池用map来实现居多) 用处:为了可重用(销毁创建麻烦,开销大)(招培训老师的例子) 二.编写实现数据库连接池 池参数: 初识 ...

  7. Java数据库连接池--DBCP浅析

    转载自   Java数据库连接池--DBCP浅析 前言对于数据库连接池, 想必大家都已经不再陌生, 这里仅仅设计Java中的两个常用数据库连接池: DBCP和C3P0(后续会更新). 一. 为何要使用 ...

  8. Java数据库开发与应用之MySQL数据库、JDBC操作数据库、C3P0数据库连接池,Java反射等

    MySQL数据库,JDBC接口,MyBatis框架等,掌握的数据的存放和管理. Java数据库开发基础,介绍MySQL数据库.JDBC操作数据库.C3P0数据库连接池,Java反射等内容,进行油画商城 ...

  9. jndi mysql数据库_数据库连接池技术中dbcp、c3p0、jndi

    数据库连接池技术中dbcp.c3p0.jndi 发布时间:2020-05-26 08:52:33 来源:51CTO 阅读:371 作者:ikilun 不管通过何种持久化技术,都必须通过数据连接访问数据 ...

最新文章

  1. 【牛客每日一题】tokitsukaze and Soldier 题目精讲 贪心、优先队列、堆
  2. linux route命令深入浅出与实战案例精讲
  3. window.location.href的target控制
  4. 点击表格获取列索引的方法
  5. [转] 让Visual Studio生成Release版本的可执行文件
  6. Swift和Objective-C混编注意事项
  7. 深度学习(四十)——深度强化学习(3)Deep Q-learning Network(2), DQN进化史
  8. linux下java程序实现重启功能
  9. 第 5 节:前端面试指南 — Vue 篇(附面试题)
  10. ORA-12899: value too large for column (actual: 27, maximum: 20)错误解决
  11. wap base.inc.php,MetInfo database.inc.php配置
  12. 终止运行线程的注意事项
  13. labview曲线上两点画延长线_零失手的‘万能眼线公式’,关键鼻翼延长线、画出适合自己的眼线...
  14. emoji表情mysql报错_让MySQL支持Emoji表情 mysql 5.6
  15. 3.0-vim编辑器和bash条件测试
  16. Shell 双引号和单引号的区别
  17. 前后端分离之后,如何保护你的API
  18. 一文掌握Pandas可视化图表
  19. 电感器饱和的简单说明
  20. 马氏距离(Mahalanobis Distance)介绍与实例

热门文章

  1. 计算机维修工教材TXT,计算机维修工.ppt
  2. rtx2060什么水平_RTX2060性能如何?NVIDIA新一代RTX2060显卡评测
  3. DHCP服务配置-Cisco模拟器
  4. 有效解决Ubuntu18.04无法联网问题
  5. c语言百文百鸡问题答案,算法的举例(。。。
  6. M.2/sata2.0/3.0接口,PCI-E1.0/2.0/3.0/4.0x2x4x8x16速率汇总
  7. 关于浏览器兼容性的问题
  8. CTFHub | Refer注入
  9. 流媒体-RTP/RTCP
  10. 【机器学习】7 支持向量机