十四 数据库连接池&DBUtils
关于数据库连接池:
1 数据库的连接对象创建工作,比较消耗性能。
2 一开始在内存中开辟一块空间,往池子里放置多个连接对象,需要连接的时候从连接池里面调用,
使用完毕归还连接,确保连接对象能够循环利用。解决jdbc中连接部分的工作
自定义数据库连接池:
/**
*
* 这是一个数据库连接池
* 1 一开始先往池子里放10个连接
* 2 通过getConnection获取连接
* 3 用完之后用addback归还连接
* 4 扩容
*
* 问题:
* 1 sun公司针对数据库连接池定义的一套规范
* 需要额外记住addBack的方法
* 2 需要做成单例
* 3 无法面向接口编程,因为接口里面没有定义addBack方法
*/
public class MyDataSource implements DataSource{ List<Connection> list = new ArrayList<>();
public MyDataSource(){
for(int i = 0; i<10 ; i++){
Connection conn = JDBCUtil.getConn();
list.add(conn);
}
} @Override
//该连接池对外公布的获取连接的方法
public Connection getConnection() throws SQLException{
//看看池子还有没有连接
if(list.size()==0){
for(int i = 0; i<10 ; i++){
Connection conn = JDBCUtil.getConn();
list.add(conn);
}
}
Connection conn = list.remove(0);
return conn;
}
//归还
public void addBack(Connection conn){
list.add(conn);
} @Override
解决自定义数据库连接池出现的问题
修改接口的close方法,Connection调用close,归还对象,而非关闭连接
如何扩展?
1. 修改源码
2. 继承,必须得知道这个接口的具体实现是谁
3. 使用装饰者模式
4. 动态代理

开源连接池:DBCP,C3P0
DBCP:Apache开发
DBCP开发的两种方式:
public class DBCPDemo {
static String driverClassName = "com.mysql.jdbc.Driver";
//jdbc主协议,mysql子协议,所以类名倒着写driverClassName为com.mysql,url为jdbc协议下mysql
//主协议:子协议://本地:数据库
static String url = "jdbc:mysql://localhost/bank";
static String username = "root";
static String password = "fungsumyuet";
@Test
//手动设置的方式
public void testDBCP01(){
Connection conn = null;
PreparedStatement ps = null;
try {
//构建数据源对象
BasicDataSource dataSource = new BasicDataSource();
//数据库连接参数
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
conn = dataSource.getConnection();
String sql = "insert into account values(null,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "bushi");
ps.setInt(2, 1000);
ps.executeUpdate();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps);
}
}
@Test
//配置文件的方式,因为是Java工程而非web工程,所以可以用IO流FileInputStream加载文件,web工程用类加载形式
public void testDBCP02(){
Connection conn = null;
PreparedStatement ps = null;
try {
BasicDataSourceFactory factory = new BasicDataSourceFactory();
Properties properties = new Properties();
InputStream is = new FileInputStream("src//dbcpconfig.properties");
properties.load(is);;
DataSource dataSource = factory.createDataSource(properties);
conn = dataSource.getConnection();
String sql = "insert into account values(null,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "liangchaowei");
ps.setInt(2, 1000);
ps.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps);
}
}
}
C3P0(重点掌握):
public class C3P0Demo01 {
@Test
//c3p0代码方式
public void testC3P0(){
//1 .创建dataSource
ComboPooledDataSource dataSource = new ComboPooledDataSource();
Connection conn = null;
PreparedStatement ps = null;
try {
//设置参数
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost/bank");
dataSource.setUser("root");
dataSource.setPassword("fungsumyuet");
conn = dataSource.getConnection();
String sql = "insert into account values(null,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "zhourunfa");
ps.setInt(2,1000);
ps.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps);
}
}
@Test
//C3P0配置文件方式
public void testC3P02(){
Connection conn = null;
PreparedStatement ps = null;
try {
//1 .创建dataSource,源码里面类加载形式加载配置文件
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//设置参数
conn = dataSource.getConnection();
String sql = "insert into account values(null,?,?)";
ps = conn.prepareStatement(sql);
ps.setString(1, "wuqilong");
ps.setInt(2,1000);
ps.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps);
}
}
}
DBUtils:联合连接池,简化CRUD操作
1.导包,引入配置文件
2.创建连接池对象,dataSource
3.将连接池对象传进QueryRunner()
4.处理业务实现功能
public class TestDBUtils {
@Test
public void demo01() throws SQLException{
//C3P0连接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
//dbUtils简化CRUD代码
QueryRunner queryRunner = new QueryRunner(dataSource);
//增加
// queryRunner.update("insert into account values(null,?,?)", "panfeng",1000);
//删除
// queryRunner.update("delete from account where id = ?", 12);
//更新
// queryRunner.update("update account set money = ? where id = ? ", 999,9);
//查询,查询到的数据还是在ResultSet里面,然后调用下面的handle方法,由用户手动去封装
/* Account account = queryRunner.query("select * from account where id = ?",
new ResultSetHandler<Account>(){
@Override
public Account handle(ResultSet rs) throws SQLException {
Account account = new Account();
while(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
int money = rs.getInt("money");
account.setId(id);
account.setName(name);
account.setMoney(money);
}
return account;
}
}, 9);
System.out.println(account.toString());*/
//查询单个对象,通过类的字节码得到该类的实例: A1 a = new A1.class.newInstance();
/*Account account = queryRunner.query("select * from account where id = ?",
new BeanHandler<Account>(Account.class),8);
System.out.println(account.toString());*/
//查询多个对象
List<Account> list = queryRunner.query("select * from account", new BeanListHandler<Account>(Account.class));
for(Account account : list){
System.out.println(account.toString());
}
}
}
DBUtil通用模版:
元数据:描述数据的数据。比如String sql , 描述sql的数据叫做元数据
public class CommonCRUDUtil {
@Test
//sql 可变参数
public void testUpdate(){
// update("insert into account values(null,?,?)","aa" , 10);
// update("delete from account where id = ?", 12);
//按照问号个数
// update02("update account set money = ? where id = ?", 800 , 7);
}
@Test
public void testQuery(){
Account account = query("select * from account where id = ?", new ResultSetHandler<Account>(){
@Override
public Account handle(ResultSet rs) {
Account account = new Account();
try {
if(rs.next()){
int id = rs.getInt("id");
String name = rs.getString("name");
int money = rs.getInt("money");
account.setId(id);
account.setName(name);
account.setMoney(money);
return account;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}}, 9 );
System.out.println(account.toString());
}
//通用的增删改查功能
/**
* @param sql
* @param args 可变参数,有几个占位符,就写几个参数进来
*/
public void update(String sql , Object ... args){
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtil02.getConn();
ps = conn.prepareStatement(sql);
//因为不知道是什么类型的数组,所以都用Object来对待
for(int i = 0 ; i<args.length ; i++){
ps.setObject(i+1, args[i]);
}
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps);
}
}
public void update02(String sql , Object ... args){
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtil02.getConn();
ps = conn.prepareStatement(sql);
//元数据,获取到有几个问号,占位符
ParameterMetaData metaData = ps.getParameterMetaData();
int count = metaData.getParameterCount();
for(int i = 0; i<count ; i++){
ps.setObject(i+1, args[i]);
}
ps.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps);
}
}
//通用查询
public <T> T query(String sql ,ResultSetHandler<T> handler, Object ... args){
Connection conn = null;
PreparedStatement ps = null;
try {
conn = JDBCUtil02.getConn();
ps = conn.prepareStatement(sql);
//元数据,获取到有几个问号,占位符
ParameterMetaData metaData = ps.getParameterMetaData();
int count = metaData.getParameterCount();
for(int i = 0; i<count ; i++){
ps.setObject(i+1, args[i]);
}
//问题1:数据获取封装成什么对象返回?
ResultSet rs = ps.executeQuery();
T t = (T) handler.handle(rs);
return t;
} catch (SQLException e) {
e.printStackTrace();
}finally {
JDBCUtil.release(conn, ps);
}
return null;
}
}
十四 数据库连接池&DBUtils的更多相关文章
- Python数据库连接池---DBUtils
Python数据库连接池DBUtils DBUtils是Python的一个用于实现数据库连接池的模块. 此连接池有两种连接模式: 模式一:为每个线程创建一个连接,线程即使调用了close方法,也不 ...
- Python数据库连接池DBUtils
Python数据库连接池DBUtils DBUtils是Python的一个用于实现数据库连接池的模块. 此连接池有两种连接模式: 模式一:为每个线程创建一个连接,线程即使调用了close方法,也不 ...
- java web学习总结(十六) -------------------数据库连接池
一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...
- javaweb学习总结(三十九)——数据库连接池
一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...
- Python数据库连接池DBUtils.PooledDB
DBUtils 是一套用于管理数据库连接池的包,为高频度高并发的数据库访问提供更好的性能,可以自动管理连接对象的创建和释放.最常用的两个外部接口是 PersistentDB 和 PooledDB,前者 ...
- Flask中使用数据库连接池 DBUtils ——(4)
DBUtils是Python的一个用于实现数据库连接池的模块. 此连接池有两种连接模式: 模式一:为每个线程创建一个连接,线程即使调用了close方法,也不会关闭,只是把连接重新放到连接池,供自己线程 ...
- python之数据库连接池DBUtils
DBUtils 是Python 的一个用于实现数据库连接池的模块. 此连接池有两种连接模式: DBUtils :提供两种外部接口: PersistentDB :提供线程专用的数据库连接,并自动管理连接 ...
- JavaWeb学习(三十)———— 数据库连接池
一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10万访问量,数据库服务器就需要创建10万次连接,极大 ...
- Python的数据库连接池DBUtils
DBUtils是Python的一个用于实现数据库连接池的模块. 此连接池有两种连接模式: 模式一:为每个线程创建一个连接,线程即使调用了close方法,也不会关闭,只是把连接重新放到连接池,供自己线程 ...
随机推荐
- 洛谷P1991 无线通讯网(最小生成树性质+连通块)
题目描述 国防部计划用无线网络连接若干个边防哨所.2 种不同的通讯技术用来搭建无线网络: 每个边防哨所都要配备无线电收发器:有一些哨所还可以增配卫星电话. 任意两个配备了一条卫星电话线路的哨所(两边都 ...
- python搭建后台服务
后端 # coding:utf-8 # 2019/10/22 16:01 # huihui # ref: from flask import Flask, abort, request, jsonif ...
- Android Studio如何更新support repository
转自: http://blog.csdn.net/sinat_29696083/article/details/70256377 刚进新公司,熟悉新业务中.老大叫我看看关于ConstraintLayo ...
- JS获取光标在input 或 texterea 中下标位置
<textarea placeholder="请输入表达式" id="methodInput" ></textarea> 获取位置: v ...
- asp.net mvc Bundle
在使用ASP.NET MVC4中使用BundleConfig 将 js css文件 合并压缩使用,但是文件名含有min及特殊字符的将不引用 ,也不提示其他信息.
- day03-Mybatis中一对一、一对多、多对多查询
一对一查询 一对一的表结构: my_account表: my_user表: 一对一是互相的,A可以找到B,B也可以找到A,方法是一样的,这里就只写一个方向的 通过my_count表找到my_user表 ...
- 「ZJOI2011」最小割
「ZJOI2011」最小割 传送门 建出最小割树,然后暴力计算任意两点之间最小割即可. 多组数据记得初始化. 参考代码: #include <algorithm> #include < ...
- 在javaweb中对于session的使用
1.初次调用session时: String username="student"; HttpSession session=request.getSession(true);// ...
- rc
1,协同过滤. 2,协方差:用来衡量,他们的变化趋势是不是一致的. 3,皮尔逊相关系数:-1,负相关.1:正相关. 4,用皮尔逊相关系数来算相关性是最多的.
- win7系统中开启wifi热点
1.进入cmd下 2.输入命令创建一个热点,名称为testwifi,密码为12345678 netsh wlan 3.进入网络和共享中心->更改适配器设置,看到多出一个“无线网络连接2”,选中本 ...