一、DbUtils简介:
DBUtils是apache下的一个小巧的JDBC轻量级封装的工具包,其最核心的特性是结果集的封装,可以直接将查询出来的结果集封装成JavaBean。使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。
可以从下载的文件中看到apidoc文档。1.4版本中,整个dbutils总共才3个包。1.7版本中,包增加到5个。使用不同版本时注意看相应的文档。
org.apache.commons.dbutils
org.apache.commons.dbutils.handlers
org.apache.commons.dbutils.handlers.columns
org.apache.commons.dbutils.handlers.properties
org.apache.commons.dbutils.wrappers
后续主要还是介绍的1.4版本的。
1、包org.apache.commons.dbutils
接口摘要
ResultSetHandler 将ResultSet转换为别的对象的工具。
RowProcessor 将ResultSet行转换为别的对象的工具。
类摘要
BasicRowProcessor RowProcessor接口的基本实现类。
BeanProcessor BeanProcessor匹配列明到Bean属性名,并转换结果集列到Bean对象的属性中。
DbUtils 一个JDBC辅助工具集合。
ProxyFactory 产生JDBC接口的代理实现。
QueryLoader 属性文件加载器,主要用于加载属性文件中的 SQL 到内存中。
QueryRunner 使用可插拔的策略执行SQL查询并处理结果集。
ResultSetIterator 包装结果集为一个迭代器。
2、包org.apache.commons.dbutils.handlersResultSetHandler接口的实现类。该接口用于处理java.sql.ResultSet,将数据按要求转换为另一种形式。ResultSetHandler接口提供了一个单独的方法:Object handle (java.sql.ResultSet .rs)。
类摘要
AbstractListHandler 将ResultSet转为List的抽象类
ArrayHandler 将ResultSet转为一个Object[]的ResultSetHandler实现类
ArrayListHandler 将ResultSet转换为List的ResultSetHandler实现类
BeanHandler 将ResultSet行转换为一个JavaBean的ResultSetHandler实现类
BeanListHandler 将ResultSet转换为List的ResultSetHandler实现类
ColumnListHandler 将ResultSet的一个列转换为List的ResultSetHandler实现类
KeyedHandler 将ResultSet转换为Map的ResultSetHandler实现类
MapHandler 将ResultSet的首行转换为一个Map的ResultSetHandler实现类
MapListHandler 将ResultSet转换为List的ResultSetHandler实现类
ScalarHandler 将ResultSet的一个列到一个对象。
3、包org.apache.commons.dbutils.wrappers添加java.sql类中功能包装类。
类摘要
SqlNullCheckedResultSet 在每个getXXX方法上检查SQL NULL值的ResultSet包装类。
StringTrimmedResultSet 取出结果集中字符串左右空格的ResultSet包装类。
二,使用DBUtils
其实只是使用的话,重点看两个类(DbUtils 和QueryRunner)和一个接口(ResultSethandler)就可以了。
1,DbUtils
DbUtils是一个为做一些诸如关闭连接、装载JDBC驱动程序之类的常规工作提供有用方法的类,它里面所有的方法都是静态的。
这个类里的重要方法有:
close():
DbUtils类提供了三个重载的关闭方法。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭连接、声明和结果集(ResultSet)。
CloseQuietly:
这一方法不仅能在连接、声明或者结果集(ResultSet)为NULL情况下避免关闭,还能隐藏一些在程序中抛出的SQLEeception。如果你不想捕捉这些异常的话,这对你是非常有用的。
在重载CloseQuietly方法时,特别有用的一个方法是closeQuietly(Connection conn,Statement stmt,ResultSet rs),这是因为在大多数情况下,连接、声明和结果集(ResultSet)是要用的三样东西,而且在最后的块必须关闭它们。使用这一方法,最后的块就可以只需要调用这一方法即可。
CommitAndCloseQuietly(Connection conn):
这一方法用来提交连接,然后关闭连接,并且在关闭连接时不向上抛出在关闭时发生的一些SQL异常。
LoadDriver(String driveClassName):
这一方法装载并注册JDBC驱动程序,如果成功就返回TRUE。这一方法装载并注册JDBC驱动程序,如果成功就返回true。使用该方法,你不需要捕捉这个异常ClassNotFoundException。
2,ResultSetHandler
这一接口执行处理一个jaca.sql.ResultSet,将数据转变并处理为任何一种形式,这样有益于其应用而且使用起来更容易。
这一组件提供了ArrayHandler, ArrayListHandler, BeanHandler, BeanListHandler, MapHandler, MapListHandler, and ScalarHandler等执行程序。
ResultSetHandler接口提供了一个单独的方法:Object handle (java.sql.ResultSet .rs)。
因此任何ResultSetHandler 的执行需要一个结果集(ResultSet)作为参数传入,然后才能处理这个结果集,再返回一个对象。因为返回类型是java.lang.Object,所以除了不能返回一个原始的Java类型之外,其它的返回类型并没有什么限制。
ArrayHandler:适合取一条记录。把结果集中的第一行数据转成对象数组。
ArrayListHandler:适合取多条记录。把结果集中的每一行数据都转成一个数组,再存放到List中。
BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。如按ID精确查询。
BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。如全表查询。
ColumnListHandler:取一列数据,将结果集中某一列的数据存放到List中。
KeyedHandler(name):取多条记录,将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
MapHandler:适合取1条记录,将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
MapListHandler:适合取多条记录,将结果集中的每一行数据都封装到一个Map里,然后再存放到List。
ScalarHandler:适合取单行单列数据 比如统计数
3,QueryRunner
这个类使执行SQL查询简单化了,它与ResultSetHandler串联在一起有效地履行着一些平常的任务,它能够大大减少你所要写的编码。
> new QueryRunner(); 它的事务可以手动控制。也就是说此对象调用的方法(如:query、update、batrch)参数中要有Connection对象。
> new QueryRunner(DataSource ds); 事务是自动控制的。一个sql一个事务,此对象调用的方法(如:query、update、batrch)参数中无需Connection对象。
QueryRunner中提供对sql语句操作的API.它主要有三个方法
query() 用于执行select
update() 用于执行insert update delete
batch() 批处理
重要方法包括以下这些:
query(Connection conn, String sql, Object[] params, ResultSetHandler rsh):
执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理PreparedStatement和ResultSet的创建和关闭。ResultSetHandler对把从 ResultSet得来的数据转变成一个更容易的或是应用程序特定的格式来使用。
query(String sql, Object[] params, ResultSetHandler rsh):
几乎与第一种一样;不同在于它不将数据库连接提供给方法,并且它是从提供给构造器的数据源(DataSource) 或使用的setDAtaSource 方法中重新获得的。
query(Connection conn, String sql, ResultSetHandler rsh):
这执行一个不要参数的选择查询。
update(Connection conn, String sql, Object[] params):
用来执行一个更新(插入、更新或删除)操作。
1.7中增加了execute、insert一系列方法。
execute(Connection conn, String sql, Object... params)
insert(Connection conn, String sql, ResultSetHandler rsh)
三、使用介绍
步骤:
> 导入jar包 加载JDBC驱动程序类,并用DriverManager来得到一个数据库连接conn。----从配置文件、直接写文件各种方式不限
> 创建QueryRunner对象
> 使用query方法执行select语句
> 使用ResultSetHandler封装结果集
> 使用DbUtils类释放资源
这里用C3P0连接池。
importjava.sql.Connection;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.util.ArrayList;importjava.util.List;importorg.apache.commons.dbutils.QueryRunner;importorg.apache.commons.dbutils.ResultSetHandler;importorg.apache.commons.dbutils.handlers.BeanListHandler;importorg.junit.Test;importcom.abc.entity.User;importcom.sun.org.apache.bcel.internal.generic.ARRAYLENGTH;public classTestCURD {
@Testpublic void testInsert() throwsSQLException{//创建一个QueryRunner对象
QueryRunner qr = newQueryRunner(C3P0Util.getDataSource());//执行sql语句
qr.update("insert into users(username,password,email,birthday) values(?,?,?,?)", "b10","123","c10@163.com",newDate());
}
@Testpublic void testUpdate() throwsSQLException{//创建一个QueryRunner对象
QueryRunner qr = newQueryRunner(C3P0Util.getDataSource());
qr.update("update users set username=?,password=? where id=?", "李明","123456",10);
}
@Testpublic void testDelete() throwsSQLException{//创建一个QueryRunner对象
QueryRunner qr = newQueryRunner(C3P0Util.getDataSource());
qr.update("delete from users where id=?", 10);
}
@Test//批处理,只能执行相同的sql语句
public void testBatch() throwsSQLException{//创建一个QueryRunner对象
QueryRunner qr = newQueryRunner(C3P0Util.getDataSource());
Object[][] params= new Object[5][];//高维代表执行多少次sql语句
for (int i = 0; i < params.length; i++) {
params[i]= new Object[]{"b10"+i,"123","c10@163.com",new Date()};//给每次执行的sql语句中的?赋值
}
qr.batch("insert into users(username,password,email,birthday) values(?,?,?,?)", params );
}
@Testpublic void testSelect() throwsSQLException{//创建一个QueryRunner对象
QueryRunner qr = newQueryRunner(C3P0Util.getDataSource());
List list = qr.query("select * from users", new ResultSetHandler>(){//当query方法执行select语句后,将结果集以参数的形式传递过来
public List handle(ResultSet rs) throwsSQLException {
List list = new ArrayList();while(rs.next()){
User u= newUser();
u.setId(rs.getInt(1));
u.setName(rs.getString(2));
u.setPassword(rs.getString(3));
u.setEmail(rs.getString(4));
u.setBirthday(rs.getDate(5));
list.add(u);
}returnlist;
}
});for(User user : list) {
System.out.println(user);
}
}
@Testpublic void testSelect2() throwsSQLException{//创建一个QueryRunner对象
QueryRunner qr = newQueryRunner(C3P0Util.getDataSource());//执行查询语句,并返回结果
List list = qr.query("select * from users where id=? and username=?", new BeanListHandler(User.class),8,"jerry");for(User user : list) {
System.out.println(user);
}
}
}
练习ResultSetHandler
importjava.sql.SQLException;importjava.util.List;importjava.util.Map;importorg.apache.commons.dbutils.QueryRunner;importorg.apache.commons.dbutils.handlers.ArrayHandler;importorg.apache.commons.dbutils.handlers.ArrayListHandler;importorg.apache.commons.dbutils.handlers.BeanHandler;importorg.apache.commons.dbutils.handlers.BeanListHandler;importorg.apache.commons.dbutils.handlers.ColumnListHandler;importorg.apache.commons.dbutils.handlers.KeyedHandler;importorg.apache.commons.dbutils.handlers.MapHandler;importorg.apache.commons.dbutils.handlers.MapListHandler;importorg.apache.commons.dbutils.handlers.ScalarHandler;importorg.junit.Test;importcom.abc.entity.User;public classTestResultSetHandler {
@Test//ArrayHandler:适合取1条记录。把该条记录的每列值封装到一个数组中Object[]
public void tese1() throwsSQLException{
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
Object[] arr= qr.query("select * from users", newArrayHandler());for(Object o : arr) {
System.out.println(o);
}
}
@Test//ArrayListHandler:适合取多条记录。把每条记录的每列值封装到一个数组中Object[],把数组封装到一个List中
public void tese2() throwsSQLException{
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
List query = qr.query("select * from users", newArrayListHandler());for(Object[] os : query) {for(Object o : os) {
System.out.println(o);
}
System.out.println("--------------");
}
}
@Test//ColumnListHandler:取某一列的数据。封装到List中。
public void tese3() throwsSQLException{
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
List list = qr.query("select username,password from users", new ColumnListHandler(1));for(Object o : list) {
System.out.println(o);
}
}
@Test//KeyedHandler:取多条记录,每一条记录封装到一个Map中,再把这个Map封装到另外一个Map中,key为指定的字段值。
public void tese4() throwsSQLException{
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());//大Map的key是表中的某列数据,小Map中的key是表的列名,所以大Map的key是Object类型,小Map的key是String类型
Map> map = qr.query("select * from users", new KeyedHandler(1));for (Map.Entry>m : map.entrySet()) {
System.out.println(m.getKey());//大Map中key值就是id列的值
for (Map.Entrymm : m.getValue().entrySet()) {
System.out.println(mm.getKey()+"\t"+mm.getValue());//取出小Map中的列名和列值
}
System.out.println("---------------------");
}
}
@Test//MapHandler:适合取1条记录。把当前记录的列名和列值放到一个Map中
public void tese5() throwsSQLException{
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
Map map = qr.query("select * from users where id=?", new MapHandler(),20);for (Map.Entrym : map.entrySet()) {
System.out.println(m.getKey()+"\t"+m.getValue());
}
}
@Test//MapListHandler:适合取多条记录。把每条记录封装到一个Map中,再把Map封装到List中
public void tese6() throwsSQLException{
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
List> list = qr.query("select * from users", newMapListHandler());for (Mapmap : list) {for (Map.Entrym : map.entrySet()) {
System.out.println(m.getKey()+"\t"+m.getValue());
}
System.out.println("---------------");
}
}
@Test//ScalarHandler:适合取单行单列数据
public void tese7() throwsSQLException{
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
Object o= qr.query("select count(*) from users", new ScalarHandler(1));
System.out.println(o.getClass().getName());
}
@Test//BeanHandler:适合取单行单列数据
public void tese8() throwsSQLException{
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
User user= qr.query("select * from users where id=?", new BeanHandler(User.class),1);
System.out.println(user);
}
@Test//BeanListHandler
public void tese9() throwsSQLException{
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
List list = qr.query("select * from users where id=?", new BeanListHandler(User.class),1);
System.out.println(list.size());
}
}
以查找图书为例
importjava.sql.SQLException;importjava.util.ArrayList;importjava.util.List;importorg.apache.commons.dbutils.QueryRunner;importorg.apache.commons.dbutils.handlers.BeanHandler;importorg.apache.commons.dbutils.handlers.BeanListHandler;importorg.apache.commons.dbutils.handlers.ColumnListHandler;importorg.apache.commons.dbutils.handlers.ScalarHandler;importcom.abc.domain.Book;importcom.abc.util.C3P0Util;importcom.sun.org.apache.bcel.internal.generic.ARRAYLENGTH;public classBookDaoImpl {/*** 查找所有图书
*@return*@throwsSQLException*/
public List findAllBooks() throwsSQLException{
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());return qr.query("select * from book", new BeanListHandler(Book.class));
}/*** 添加图书信息
*@parambook
*@throwsSQLException*/
public void addBook(Book book) throwsSQLException{
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
qr.update("INSERT INTO book VALUES(?,?,?,?,?,?)",book.getId(),book.getName(),book.getPrice(),book.getPnum(),book.getCategory(),book.getDescription());
}/***
*@paramid
*@return*@throwsSQLException*/
public Book findBookById(String id) throwsSQLException {
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());return qr.query("select * from book where id=?", new BeanHandler(Book.class),id);
}/*** 修改图书信息
*@parambook
*@throwsSQLException*/
public void updateBook(Book book) throwsSQLException {
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
qr.update("update book set name=?,price=?,pnum=?,category=?,description=? where id=?",
book.getName(),book.getPrice(),book.getPnum(),book.getCategory(),book.getDescription(),book.getId());
}/*** 根据id删除图书
*@paramid
*@throwsSQLException*/
public void delBook(String id) throwsSQLException {
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
qr.update("delete from book where id=?",id);
}/*** 批量删除
*@paramids
*@throwsSQLException*/
public void deleAllBooks(String[] ids) throwsSQLException {
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
Object[][] params= newObject[ids.length][];for (int i = 0; i < params.length; i++) {
params[i]= new Object[]{ids[i]};//循环给每个一维数组中的元素赋值,值是id
}
qr.batch("delete from book where id=?", params );
}/*** 多条件查询图书
*@paramid
*@paramcategory
*@paramname
*@paramminprice
*@parammaxprice
*@return*@throwsSQLException*/
public ListsearchBooks(String id, String category, String name,
String minprice, String maxprice)throwsSQLException {
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());
String sql= "select * from book where 1=1";
List list= newArrayList();if(!"".equals(id.trim())){
sql+=" and id like ?"; //不能在这写% %'1003'%
list.add("%"+id.trim()+"%");//'%1003%'
}if(!"".equals(category.trim())){
sql+=" and category=?";
list.add(category.trim());
}if(!"".equals(name.trim())){
sql+=" and name like ?";
list.add("%"+name.trim()+"%");
}if(!"".equals(minprice.trim())){
sql+=" and price>?";
list.add(minprice.trim());
}if(!"".equals(maxprice.trim())){
sql+=" and price< ?";
list.add(maxprice.trim());
}return qr.query(sql, new BeanListHandler(Book.class),list.toArray());
}/*** 得到总记录数
*@return*@throwsSQLException*/
public int count() throwsSQLException {
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());long l = (Long)qr.query("select count(*) from book", new ScalarHandler(1));return (int)l;
}/*** 查找分页数据
*@paramcurrentPage
*@parampageSize
*@return*@throwsSQLException*/
public List findBooks(int currentPage, int pageSize) throwsSQLException {
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());return qr.query("select * from book limit ?,?", new BeanListHandler(Book.class),(currentPage-1)*pageSize,pageSize);
}/*** 根据书名查找图书 模糊查询
*@paramname
*@return*@throwsSQLException*/
public List searchBookByName(String name) throwsSQLException {
QueryRunner qr= newQueryRunner(C3P0Util.getDataSource());return qr.query("select name from book where name like ?", new ColumnListHandler(),"%"+name+"%");
}
}
参考资料: