开源JDBC工具类DbUtils
本篇将会详细地介绍Apache公司的JDBC帮助工具类DbUtils以及如何使用。在上一篇中我们已经通过将以前对dao层使用JDBC操作数据库的冗余代码进行了简易封装形成自己的简单工具类JdbcUtils,而在这过程中很多都是借鉴和参考了DbUtils的代码,因此通过上一篇的学习,会让我们在对DbUtils进行更快速简单的认识。
俗话说学习一个开源的工具最好的方法就是看其官方文档,是的,在Apache官网中对DbUtils进行了详细的介绍:http://commons.apache.org/proper/commons-dbutils/ 。(或者下载了DbUtils的jar中也有相应文档)
DbUtils是一些类组成的用于简化JDBC开发的库,解决我们以前根据“模板”代码写出的大部分的冗余部分,将我们的代码进行最大程度的简化,使我们只关心于查询和更新(包括添加、修改和删除)数据。就好像上一篇博客中我们重点写的query和update方法。
DbUtils能做些什么?虽然JDBC代码不难,但是根据我们以前所写的“模板”代码费时又费力,非常容易丢失链接并且难以追寻,而使用DbUtils基本不会发生资源泄露(比如链接的丢失)。当然和上一篇博文相同,DbUtils也提供了一个对结果集处理的接口ResultSetHandler,我们可以实现这个接口来对结果集进行处理,也可以使用DbUtils提供的实现类,例如BeanHandler或者BeanListHandler等等,有很多实用的结果集处理器类。如果有一些公司不使用hibernate的话一般会选用DbUtils。
DbUtils最主要的就两个,QueryRunner类和ResultSetHandler接口。
QueryRunner类这个类主要用于提供各种重载形式的batch方法、query方法和update 方法,其中update 方法包含添加、删除和修改。
QueryRunner并不算一个静态工具类,因此我们要使用必须先创建一个QueryRunner类的对象,而这就有两种构造器,分别是无参的和有参的,其中有参的构造器接收一个连接池对象DataSource。


可以从手册中看到,如果在创建QueryRunner对象时给定了一个连接池对象,那么在一些不需要Connection对象为参数的方法被调用时会从连接池中自动获取连接,调用完后会将连接重新返回到连接池中;而对于无参的构造器来说,在调用方法时必须指定Connection对象,同时调用完方法后Connection对象的处理要自己负责。
下面就看看对于无参和有参的QueryRunner对象的各种重载形式的query方法和update方法:


可以看到这些方法中主要就分为两种,一种是有Connection对象参数的,一种是无Connection对象参数的。上面已经说过了,无Connection对象参数的方法是从有参QueryRunner的连接池中获取链接,同时会自动将连接返还给连接池。而有Connection参数的方法由调用者负责关闭连接,这种方法看似麻烦,但是由多条SQL组成的事务进行整体执行却是必须的,因为我们不需要只执行一条SQL就还给连接池。
除了query方法和update方法,QueryRunner类还有一个batch方法,用于执行SQL批处理:

这个方法用于对某一条SQL执行多次,而我们提供给这个方法的参数中是一个二维数组,那么怎么用呢?
比如“insert into user(id,name,age) values(?,?,?)”这样的SQL语句,batch方法中的二维数组参数就可以是 [ [1,”Ding”,25],[2,”LRR”,24] ] 这样的形式,也就是批处理执行两次,而每次的参数都不同。
上面的介绍基本就是QueryRunner的全部,当然QueryRunner只是DbUtils的一部分,而另一部分在于QueryRunner中query方法参数中的ResultSetHandler接口,用于处理结果集,这一点上一篇博客已经讲述的很清楚了。而在DbUtils中为我们已经写好了更多的这个接口的实现类:

除了我们上一篇博客自己动手实现的BeanHandler和BeanListHandler之外,在DbUtils中可以使用便捷的结果集处理器还有
ArrayHandler:把结果集中的第一行数据封装进对象数组中。
ArrayListHandler:把结果集中的每一行数据封装进数组,再将这些数组存进List集合中。
ColumnListHandler:将结果集中的某一列所有的数据存进List集合中。
KeyedHandler:将结果集中的每一行数据封装进一个Map中,再把这些Map存到一个Map里,其Key为指定的Key。
MapHandler:将结果集中的第一行数据封装进Map里,Key为列名,value就是对应的值。
MapListHandler:将结果集中的每一行数据封装到Map中,再将这些Map存放进List中。
记得上一篇博客中我们在JDBC工具类JdbcUtils中重点创建的自定义的update方法和query方法吗(上一篇博客的第四点和第五点),那只是为了我们将冗余代码进行封装,而在本篇中我们可以在JdbcUtils中删了这里两个方法,而直接在dao层中使用DbUtils进行低层的增删改查。
例1:
那么在下面的代码中就对上一篇博客最后的UserDao中的增删改查进行重构:
public class UserDao {
// 添加用户
public void add(User user) throws SQLException {
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
String sql = "insert into user(id,name,age) values(?,?,?)";
Object[] params = { user.getId(), user.getName(), user.getAge() };
qr.update(sql, params);
}
// 删除用户
public void delete(int id) throws SQLException {
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
String sql = "delete from user where id=?";
Object params = id;
qr.update(sql, params);
}
// 修改用户
public void update(User user) throws SQLException {
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
String sql = "update user set name=?,age=? where id=?";
Object[] params = { user.getName(), user.getAge(), user.getId() };
qr.update(sql, params);
}
// 查找某个用户
public User find(int id) throws SQLException {
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from user where id=?";
Object params = id;
User user = qr.query(sql, new BeanHandler<>(User.class), params);
return user;
}
// 列出所有用户
public List<User> getAllUser() throws SQLException {
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from user";
List<User> list = qr.query(sql, new BeanListHandler<>(User.class));
return list;
}
}
可以看到使用QueryRunner就将我们的增删改查语句变得非常简单,同时我们在工具类JdbcUtils中也不用另外再写update方法和query方法,在JdbcUtils中主要是创建连接池。由于我们在创建QueryRunner对象时使用了DataSource作为参数,这样我们在使用无Connection对象的update方法和query方法都可以不用指定连接,同时这些方法会将我们的连接自动放回连接池,因此我们在JdbcUtils甚至都可以不用写释放资源的代码(当然具体情况具体分析)。
例2:
再补充一个使用DbUtils的批处理batch方法的demo:
public void batchInsertTest() throws SQLException {
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
String sql = "insert into user(id,name,age) values(?,?,?)";
Object[][] params = new Object[5][3];
for(int i=0;i<params.length;i++) {
params[i] = new Object[]{i+1,"aa"+i,25+i};
}
qr.batch(sql, params);
}
结果如下:

关于DbUtils中的QueryRunner类就差不多介绍完了,主要就是batch、query和update 方法。
而对于结果集处理器类,DbUtils给我们提供了很多针对ResultSetHandler接口的实现类,如果这些实现类都不能满足我们的需要,我们也可以实现ResultSetHandler接口来制作我们所需要功能的实现类。
例3:
下面使用DbUtils中的结果集处理器类之一的ArrayHandler类来简单演示下demo(以上面批处理batch方法调用后的数据库中数据为例):
public void arrayHandlerTest() throws SQLException {
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select * from user";
Object[] firstUser = qr.query(sql, new ArrayHandler());
for(Object o:firstUser) {
System.out.println(o);
}
}
ArrayHandler类只将结果集的第一行数据封装进一个对象数组中,在控制台观察:

例4:
有时候我们需要计算一张表中的总记录数,例如在使用数据库进行分页的时候就需要知道有多少数据,那么将查询结果以结果集返回也可以使用ArrayHandler简单处理,因为数组的第一个元素就是查询结果,但下面的代码看似没有问题,却在运行时会抛出异常:
public void countTest() throws SQLException {
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select count(*) from user";
Object[] result = qr.query(sql, new ArrayHandler());
int count = (int) result[0];
System.out.println(count);
}
异常原因:

也就是说在MySQL中以count方法在JDBC中是以Long类型返回查询的数值,因此我们不能只用Integer类型。这点要注意,但是总记录数不大时可以将Long类型强制转换为Integer类型:
public void countTest() throws SQLException {
QueryRunner qr = new QueryRunner(JdbcUtils.getDataSource());
String sql = "select count(*) from user";
Object[] result = qr.query(sql, new ArrayHandler());
int count = ((Long)result[0]).intValue();
System.out.println(count);
}
当然还有其他的很实用的结果集处理器类,这里就不一一介绍了。本篇对DbUtils的讲解就结束了,对于DbUtils的使用是很简单的,只要掌握了QueryRunner类和ResultSetHandler接口及其实现类,就能很好的掌握DbUtils。
开源JDBC工具类DbUtils的更多相关文章
- JDBC工具类-DButils(QueryRunner-ResultSetHandler)
简述: DBUtils是Java编程中的数据库操作实用工具,小巧简单实用. DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码. DBUtils三个核心功能: QUeryRunne ...
- Apache—dbutils开源JDBC工具类库简介
Apache—dbutils开源JDBC工具类库简介 一.前言 commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用 ...
- 自己实现的JDBC工具类
最近做了个后台应用程序,刚开始用Spring+iBatis来做的,后来因为种种原因,不让用Spring.iBatis以及一些开源的工具包. 于是用JDBC重写了原来的Service实现,项目做完了 ...
- MySQL数据库学习笔记(十一)----DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- MySQL数据库学习笔记(十)----JDBC事务处理、封装JDBC工具类
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...
- MySQL JDBC事务处理、封装JDBC工具类
MySQL数据库学习笔记(十)----JDBC事务处理.封装JDBC工具类 一.JDBC事务处理: 我们已经知道,事务的概念即:所有的操作要么同时成功,要么同时失败.在MySQL中提供了Commit. ...
- DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类)
DAO设计模式实现数据库的增删改查(进一步封装JDBC工具类) 一.DAO模式简介 DAO即Data Access Object,数据访问接口.数据访问:故名思义就是与数据库打交道.夹在业务逻辑与数据 ...
- JDBC_14_使用JDBC工具类实现模糊查询
使用JDBC工具类实现模糊查询 代码: import java.sql.*; /** * 模糊查询 * 测试DBUtils */ public class JDBCTest09 { public st ...
- jdbc 11: 封装自己的jdbc工具类
jdbc连接mysql,封装自己的jdbc工具类 package com.examples.jdbc.utils; import java.sql.*; import java.util.Resour ...
随机推荐
- cocos2d-x游戏开发系列教程-超级玛丽10-怪物与马里奥冲突检测
在超级玛丽游戏中,马里奥在移动,怪物也在移动,当他们遇见时,需要判断是马里奥身亡还是怪物身亡. 这个判断的代码在怪物类的检测函数实现中. 比如蘑菇怪的冲突检测函数: bool CMMonsterMus ...
- BZOJ 1610: [Usaco2008 Feb]Line连线游戏
1610: [Usaco2008 Feb]Line连线游戏 Description Farmer John最近发明了一个游戏,来考验自命不凡的贝茜.游戏开始的时 候,FJ会给贝茜一块画着N (2 &l ...
- [Unity 3D] Unity 3D 性能优化(二)
IsAlive U3D的粒子系统脚本接口相信很多人都用过,ParticleSyetem类的一系列接口都有一个bool类型的参数——withChildren,通过这个参数可以直接将相同的判断或者操作应用 ...
- stm32之GPIO
stm32有5组GPIO口,GPIOA GPIOB GPIOC GPIOD GPIOE 每个GPIO端口有: 2个配置寄存器GPIOx_CRL, GPIOx_CRH(32位): 2个数据寄存器GPIO ...
- Xcode7网络限制
在info.plist添加字段 App Transport Security Settings Allow Arbitrary Loads yes
- input file 在开发中遇到的问题 类似ajax form表单提交 input file中的文件
最近在做项目的过程中遇到个问题,在这里做个记录防止日后忘记 现今的主流浏览器由于ajax提交form表单无法把文件类型数据提交到后台,供后台处理,可是开发中由于某些原因又不得不用ajax提交文件, 为 ...
- 我的Python成长之路---第三天---Python基础(12)---2016年1月16日(雾霾)
四.函数 日常生活中,要完成一件复杂的功能,我们总是习惯把“大功能”分解为多个“小功能”以实现.在编程的世界里,“功能”可称呼为“函数”,因此“函数”其实就是一段实现了某种功能的代码,并且可以供其它代 ...
- excel列显示形式互换(字母与数字)
以office2007为例: excel选项>公式>使用公式下的'R1C1引用样式' 打上钩显示形式为数字,不打钩显示形式为字母
- QT实现图片按钮(用qss切割图片,或者放三张图片)
我在网上找了很久,把他综合了一下 不说了关键代码来了:(这是一张图片切图的效果) void SetButtonStyle(QPushButton *button, QString imgsrc, in ...
- Tri_integral Summer Training 8 总结
比赛链接 题目 B C E F G I 这是孟加拉国的区域赛. 开场ss读懂了c发现是个水题,于是去敲,结果手贱wa了一炮,不过很快就修正了错误.B题过了不少,我去读,发现是个水题,意识让Moor敲. ...