十五、Apache—DBUtils框架

时间:2021-04-05 13:14:16
简介
commons-dbutils 是 Apache 组织提供的一个开源 JDBC 工具类库,它是对 JDBC 的简单封装,学习成本极低,并且使用 dbutils 能极大简化 jdbc 编码的工作量,同时也不会影响程序的性能。因此 dbutils 成为很多不喜欢 hibernate 的公司的首选。

DbUtils的核心API
DbUtils 简化了数据库的CRUD的操作 、提供了如关闭连接,装载驱动程序等常规操作的工具类,核心API有3个,
QueryRunner类、 ResultSetHandler接口、 DbUtils工具类,源码结构如下:
十五、Apache—DBUtils框架

QueryRunner类
简化了SQL的CRUD操作(与ResultSetHandler接口组合可以完成大部分的数据查询操作,能够大大减少编码量)
构造函数:
QueryRunner() (手动管理事务)
QueryRunner(DataSource ds)(自动管理事务)

主要方法:

public Object query(Connection conn, String sql, Object[] params, ResultSetHandler rsh) throws SQLException:执行一个查询操作,在这个查询中,对象数组中的每个元素值被用来作为查询语句的置换参数。该方法会自行处理 PreparedStatement ResultSet 的创建和关闭。

 
public Object query(String sql, Object[] params, ResultSetHandler rsh) throws SQLException: 几乎与第一种方法一样;唯一的不同在于它不将数据库连接提供给方法,并且它是从提供给构造方法的数据源 (DataSource) 或使用的 setDataSource 方法中重新获得 Connection
 
public Object query(Connection conn, String sql, ResultSetHandler rsh) throws SQLException : 执行一个不需要置换参数的查询操作。
 
public int update(Connection conn, String sql, Object[] params) throws SQLException:用来执行一个更新(插入、更新或删除)操作。
 
public int update(Connection conn, String sql) throws SQLException:用来执行一个不需要置换参数的更新操作。


DbUtils类
提供如关闭连接、装载 JDBC 驱动程序等常规工作的工具类,里面的所有方法都是静态的。
类提供了三个重载的关闭方法。这些方法检查所提供的参数是不是NULL,如果不是的话,它们就关闭ConnectionStatementResultSet

主要方法:
public static void close(… ) throws java.sql.SQLException
 
public static void closeQuietly(… ): 这一类方法不仅能在 Connection Statement ResultSet NULL 情况下避免关闭,还能隐藏一些在程序中抛出的 SQLEeception

public static void commitAndCloseQuietly(Connection conn): 用来提交连接,然后关闭连接,并且在关闭连接时不抛出 SQL 异常。

public static boolean loadDriver(java.lang.String driverClassName):这一方装载并注册 JDBC 驱动程序,如果成功就返回 true 。使用该方法,你不需要捕捉这个异常 ClassNotFoundException


ResultSetHandler接口
该接口用于处理 java.sql.ResultSet,将数据按要求转换为另一种形式。
ResultSetHandler 接口提供了一个单独的方法: Object handle (java.sql.ResultSet .rs)

ResultSetHandler 接口的实现类
ArrayHandler:把结果集中的第一行数据转成对象数组。
ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到 List 中。
BeanHandler:将结果集中的第一行数据封装到一个对应的 JavaBean 实例中。
BeanListHandler:将结果集中的每一行数据都封装到一个对应的 JavaBean 实例中,存放到 List 里。
ColumnListHandler:将结果集中某一列的数据存放到 List 中。
KeyedHandler(name):将结果集中的每一行数据都封装到一个 Map< 列名 , 列值 > 里,再把这些 map 再存到一个 map 里,其 key 为指定的 key
MapHandler:将结果集中的第一行数据封装到一个 Map 里, key 是列名, value 就是对应的值。
MapListHandler:将结果集中的每一行数据都封装到一个 Map 里,然后再存放到 List
ScalarHandler: 用于做单值查询的情况 . 查询有效数据的个数。
当然如果上面的都觉得不够用,你完全可以自行实现ResultSetHandler 接口进行处理。

下面通过demo来演示dbutils的使用。

项目工程如下:

十五、Apache—DBUtils框架

测试的数据库结构如下:

十五、Apache—DBUtils框架

demo1

package demo1;

import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class Demo1 {

	private QueryRunner qrunner = new QueryRunner(new ComboPooledDataSource());

	/**
	 * 使用dbutils的增、删、改的方法
	 * 
	 * @throws Exception
	 */
	@Test
	public void testUpdate() throws Exception {
		// 测试insert
		qrunner.update("insert into account values(null,'zs',200);");

		// 测试delete
		qrunner.update("delete from account where name = ?", "a");

		// 测试update
		qrunner.update("update account set money = ? where name = ?", 1000, "b");

	}
}

demo2

package demo2;

import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.junit.Test;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import bean.Account;

public class Demo2 {

	private QueryRunner qrunner = new QueryRunner(new ComboPooledDataSource());

	/**
	 * 测试用BeanListHandler处理查询结果,返回一个集合bean
	 * 
	 * @throws Exception
	 */
	@Test
	public void testBeanListHandler() throws Exception {
		List<Account> list = qrunner.query("select * from account where money > ?",
				new BeanListHandler<Account>(Account.class), 100);

		for (Account account : list) {
			System.out.println(account);
		}
	}

	/**
	 * 测试用ColumnListHandler处理查询结果,返回某一列的所有值
	 * 
	 * @throws Exception
	 */
	@Test
	public void testColumnListHandler() throws Exception {
		/*
		 * List<Object> list = qrunner.query("select * from account where money > ?",
		 * new ColumnListHandler("name"), 100);
		 */

		List<Object> list = qrunner.query("select * from account", new ColumnListHandler("name"));

		for (Object value : list) {
			System.out.println(value);
		}
	}

	/**
	 * 测试用ScalarHandler处理聚合函数的查询结果
	 * 
	 * @throws Exception
	 */
	@Test
	public void testScalarHandler() throws Exception {
		Long count = (Long) qrunner.query("select count(*) from account", new ScalarHandler());

		System.out.println(count);
	}

	/**
	 * 测试用MapListHandler处理查询结果
	 * 
	 * @throws Exception
	 */
	@Test
	public void testMapListHandler() throws Exception {
		List<Map<String, Object>> list = qrunner.query("select * from account", new MapListHandler());
		
		for (Map<String, Object> map : list) {
			for (String key : map.keySet()) {
				System.out.println("key:" + key + " values:" + map.get(key));
			}
		}

	}
}

account

package bean;

/**
 * 和数据库对应的实体,必须要有set方法,因为dbutils是通过set方法来设置字段的
 * 
 * @author mChenys
 *
 */
public class Account {

	public int id;
	public String name;
	public double money;

	public void setId(int id) {
		this.id = id;
	}

	public void setName(String name) {
		this.name = name;
	}

	public void setMoney(double money) {
		this.money = money;
	}

	@Override
	public String toString() {
		return "Account [id=" + id + ", name=" + name + ", money=" + money + "]";
	}

}
关于c3p0连接池的配置可以看这里 十二、数据库连接池