开源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 ...
随机推荐
- IT第十天 - String和StringBuffer的比较、编程设计技巧整理、本周总结 ★★★
IT第十天 上午 String 1.String在进行多次的+扩展时,会严重的降低处理效率,因为String长度是不可变的,在进行+运算改变字符串时,会自动创建很多临时字符串,并不是在原字符串上追加, ...
- Vijos P1067Warcraft III 守望者的烦恼
题目 背景 守望者-warden,长期在暗夜精灵的的首都艾萨琳内担任视察监狱的任务,监狱是成长条行的,守望者warden拥有一个技能名叫“闪烁”,这个技能可以把她传送到后面的监狱内查看,她比较懒,一般 ...
- Android zip文件压缩解压缩
DirTraversal.java <P style="TEXT-ALIGN: left; PADDING-BOTTOM: 0px; WIDOWS: 2; TEXT-TRANSFORM ...
- 为了肾六(dp)
为了肾六 时间限制:4000 ms | 内存限制:210535 KB 难度:2 描述 最近肾六很流行,goshawk看身边的朋友都用上了apple.自己还用着W年前的Samsung.于是决定去 ...
- hadoop、spark/storm等大数据相关视频资料汇总下载
小弟不才,工作中也用到了大数据的相关东西.一開始接触的时候,是通过买来的教学视频入的门.这两天整理了一下自己的视频资料.供各位进行下载. 文档截图:
- aspx.cs上传文件
aspx.cs文件 using System; using System.Collections.Generic; using System.Linq; using System.Web; using ...
- 使用阿里云集成包快速搭建LAMP+FTP教程
LAMP集成包安装步骤 1.下载开发集成包 下载最新版的阿里云市场提供的WEB开发集成包(内含Apache.Mysql.PHP.vsftpd) #Linux指令wget http://gongdan. ...
- 在树莓派上设置无线静态IP
修改文件: /etc/network/interfaces,命令如下 sudo nano /etc/network/interfaces 将最后一句iface default inet dhcp,替换 ...
- Python之路Day9
摘要: 协程 Select\Poll\Epoll异步IO与事件驱动 Python连接MySQL数据库操作 RabbitMQ队列 Redis\Memcached缓存 Paramiko Twsited网络 ...
- QuartusII 中使用Modelsim对子程序进行仿真
QuartusII 中使用Modelsim对子程序进行仿真 如果采用RTL级仿真那么就没有任何问题,但是如果对子程序采用门级仿真就会出错 解决办法:在Project Navigator中右键需要进行门 ...