DBUtils介绍与使用

如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC开发,本案例我们讲采用apache commons组件一个成员:DBUtils。DBUtils就是JDBC的简化开发工具包。需要项目导入commons-dbutils-1.6.jar才能够正常使用DBUtils工具。

1.1 概述

DBUtils是java编程中的数据库操作实用工具,小巧简单实用。

DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。

Dbutils三个核心功能介绍

   QueryRunner中提供对sql语句操作的API.

   ResultSetHandler接口,用于定义select操作后,怎样封装结果集.

   DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法


1.2准备数据

  创建表

create table product(
	pid int primary key,
	pname varchar(20),
	price double,
	category_id varchar(32)
);

    插入数据

INSERT INTO product(pid,pname,price,category_id) VALUES(1,'联想',5000,'c001');
INSERT INTO product(pid,pname,price,category_id) VALUES(2,'海尔',3000,'c001');
INSERT INTO product(pid,pname,price,category_id) VALUES(3,'雷神',5000,'c001');

INSERT INTO product(pid,pname,price,category_id) VALUES(4,'JACK JONES',800,'c002');
INSERT INTO product(pid,pname,price,category_id) VALUES(5,'真维斯',200,'c002');
INSERT INTO product(pid,pname,price,category_id) VALUES(6,'花花公子',440,'c002');
INSERT INTO product(pid,pname,price,category_id) VALUES(7,'劲霸',2000,'c002');

INSERT INTO product(pid,pname,price,category_id) VALUES(8,'香奈儿',800,'c003');
INSERT INTO product(pid,pname,price,category_id) VALUES(9,'相宜本草',200,'c003');
INSERT INTO product(pid,pname,price,category_id) VALUES(10,'面霸',5,'c003');

INSERT INTO product(pid,pname,price,category_id) VALUES(11,'好想你枣',56,'c004');
INSERT INTO product(pid,pname,price,category_id) VALUES(12,'香飘飘奶茶',1,'c005');

INSERT INTO product(pid,pname,price,category_id) VALUES(13,'果9',1,NULL);

sql运行结果:



1.3QueryRunner核心类介绍(两种方式创建对象)

1.3.1     提供数据源

   构造方法

     QueryRunner(DataSource) 创建核心类,并提供数据源,内部自己维护Connection

   普通方法

   update(String sql , Object ... params) 执行DML语句(包括增删改)

   query(String sql , ResultSetHandler , Object ... params) 执行DQL语句,并将查询结果封装到对象中。


1.3.2提供连接

   构造方法

    QueryRunner() 创建核心类,没有提供数据源,在进行具体操作时,需要手动提供Connection

   普通方法

    update(Connection conn , String sql ,Object ... params) 使用提供的Connection,完成DML语句(增删改)

    query(Connection conn , String sql ,ResultSetHandler , Object ... params) 使用提供的Connection,执行DQL语句,并将查询结果封装到对象中。


1.4     QueryRunner实现添加、更新、删除操作

   update(String sql, Object... params) ,用来完成表数据的增加、删除、更新操作

项目结构是这样的:


C3P0Utils代码是:

package com.demo_01_utils;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

/**
 * 等效 JdbcUtils,用于提供获得连接工具类
 */
public class C3P0Utils {
	
	//连接池
	private static ComboPooledDataSource dataSource = new ComboPooledDataSource("wulin"); 
	
	/**
	 * 获得数据源(连接池)
	 * @return
	 */
	public static DataSource getDataSource(){
		return dataSource;
	}
	
	
	/**
	 * 获得连接
	 * @return
	 * @throws SQLException 
	 */
	public static Connection getConnection() throws SQLException{
		//将从连接池中获得连接
		return dataSource.getConnection();
	}
	
	

}

c3p0-config.xml是:

<c3p0-config>
	<!-- 命名的配置 -->
	<named-config name="wulin">
		<!-- 连接数据库的4项基本参数 -->
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="jdbcUrl">jdbc:mysql://127.0.0.1:3306/webdb_4</property>
		<property name="user">root</property>
		<property name="password">root</property>
		<!-- 如果池中数据连接不够时一次增长多少个 -->
		<property name="acquireIncrement">5</property>
		<!-- 初始化连接数 -->
		<property name="initialPoolSize">20</property>
		<!-- 最小连接受 -->
		<property name="minPoolSize">10</property>
		<!-- 最大连接数 -->
		<property name="maxPoolSize">40</property>
		<!-- -JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量 -->
		<property name="maxStatements">0</property>
		<!-- 连接池内单个连接所拥有的最大缓存statements数 -->
		<property name="maxStatementsPerConnection">5</property>
	</named-config>
</c3p0-config>


javaBean

JavaBean就是一个类,在开发中常用语封装数据。具有如下特性

1.        需要实现接口:java.io.Serializable,通常实现接口这步骤省略了,不会影响程序。

2.        提供私有字段:private 类型字段名;

3.        提供getter/setter方法:

4.        提供无参构造

 Product代码是:

package com.demo_03_javabean;

public class Product {
	
	private Integer pid;
	private String pname;
	private Double pirce;
	private String category_id;
	
	public Integer getPid() {
		return pid;
	}
	public void setPid(Integer pid) {
		this.pid = pid;
	}
	public String getPname() {
		return pname;
	}
	public void setPname(String pname) {
		this.pname = pname;
	}
	public Double getPirce() {
		return pirce;
	}
	public void setPirce(Double pirce) {
		this.pirce = pirce;
	}
	public String getCategory_id() {
		return category_id;
	}
	public void setCategory_id(String category_id) {
		this.category_id = category_id;
	}
	@Override
	public String toString() {
		return "Product [pid=" + pid + ", pname=" + pname + ", pirce=" + pirce + ", category_id=" + category_id + "]";
	}

	
}

1.4.1添加

@Test
	public void demo01() throws SQLException{
		//遵循原则,有异常抛
		//1 核心类
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		
		//2 执行update方法
		int r = queryRunner.update("insert into product(pid,pname,price,category_id) values(?,?,?,?)", 99,"测试",100,"c009");
		
		System.out.println(r);//返回的是影响的行数
		
	}
	
	@Test
	public void demo02() throws SQLException{
		//将sql和实际参数 进行抽取
		//1 核心类
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		
		//2 执行update方法
		String sql = "insert into product(pid,pname,price,category_id) values(?,?,?,?)";
		Object[] params = { 990,"测试",100,"c009" };
		int r = queryRunner.update(sql,params);
		
		System.out.println(r);
		
	}

运行结果:



1.4.2更新

@Test
	public void demo03() throws SQLException{
		//1 核心类
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		//2 准备sql语句
		String sql = "update product set pname=?,price=?,category_id=? where pid=?";
		
		//3 准备实际参数
		Object[] params = {"芒果99","998","c009",13};
		
		//4 执行
		int r = queryRunner.update(sql, params);
		System.out.println(r);
		
	}

运行结果:




1.4.3删除

@Test
	public void demo04() throws SQLException{
		
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		String sql = "delete from product where pid = ?";
		Object[] params = {99};
		int r = queryRunner.update(sql, params);
		System.out.println(r);
				
	}

运行结果(与上图做比较):




1.5QueryRunner实现查询操作

    query(String sql, ResultSetHandler<T> rsh, Object... params) ,用来完成表数据的查询操作


1.5.1ResultSetHandler结果集处理类

后面会一一介绍如下这么多Handler:

ArrayHandler

将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值

ArrayListHandler

将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。

BeanHandler

将结果集中第一条记录封装到一个指定的javaBean中。

BeanListHandler

将结果集中每一条记录封装到指定的javaBean中,将这些javaBean在封装到List集合中

ColumnListHandler

将结果集中指定的列的字段值,封装到一个List集合中

KeyedHandler

将结果集中每一条记录封装到Map<String,Object>,在将这个map集合做为另一个Map的value,另一个Map集合的key是指定的字段的值。

MapHandler

将结果集中第一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值

 

MapListHandler

将结果集中每一条记录封装到了Map<String,Object>集合中,key就是字段名称,value就是字段值,在将这些Map封装到List集合中。

ScalarHandler

它是用于单数据。例如select count(*) from 表操作。


1.5.2BeanHandler

/*
	 * 查询数据表结果集处理其中一种方式:
	 *   BeanHandler处理方式
	 *     将数据表的结果集第一行数据,封装成JavaBean类的对象
	 *   构造方法:
	 *    BeanHandler(Class<T> type) 
	 *    传递一个Class类型对象,将结果封装到哪个类的对象呢
	 *    Product类的Class对象
	 */
	@Test
	public void demo01() throws SQLException{
		// 通过id查询详情,将查询结果封装到JavaBean product
		
		//1核心类 
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		//2 sql语句
		String sql = "select * from product where pid = ?";
		//3 实际参数
		Object[] params = {6};
		//4 查询并封装
		Product product = queryRunner.query(sql, new BeanHandler<Product>(Product.class), params);
		
		System.out.println(product);
	}

运行结果:

Product [pid=6, pname=花花公子, pirce=null, category_id=c002]



1.5.3BeanListHandler

/*
	 * 查询数据表结果集处理其中一种方式:
	 *   BeanListHandler处理方式
	 *   将数据表的每一行数据,封装成JavaBean类对象
	 *   多行数据了,多个JavaBean对象,存储List集合
	 */
	@Test 
	public void demo02() throws SQLException{
		//查询所有,将每一条记录封装到一个JavaBean,然后将JavaBean添加到List中,最后返回List,BeanListHandler
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		String sql = "select * from product";
		Object[] params = {};
		List<Product> list = queryRunner.query(sql, new BeanListHandler<Product>(Product.class), params);
		
		for(Product product : list){
			System.out.println(product);
		}
	}

运行结果:

Product [pid=1, pname=联想, pirce=null, category_id=c001]
Product [pid=2, pname=海尔, pirce=null, category_id=c001]
Product [pid=3, pname=雷神, pirce=null, category_id=c001]
Product [pid=4, pname=JACK JONES, pirce=null, category_id=c002]
Product [pid=5, pname=真维斯, pirce=null, category_id=c002]
Product [pid=6, pname=花花公子, pirce=null, category_id=c002]
Product [pid=7, pname=劲霸, pirce=null, category_id=c002]
Product [pid=8, pname=香奈儿, pirce=null, category_id=c003]
Product [pid=9, pname=相宜本草, pirce=null, category_id=c003]
Product [pid=10, pname=面霸, pirce=null, category_id=c003]
Product [pid=11, pname=好想你枣, pirce=null, category_id=c004]
Product [pid=12, pname=香飘飘奶茶, pirce=null, category_id=c005]
Product [pid=13, pname=芒果99, pirce=null, category_id=c009]
Product [pid=990, pname=测试, pirce=null, category_id=c009]


1.5.4ScalarHander

/*
	 * 查询数据表结果集处理其中一种方式:
	 *    ScalarHandler处理方式
	 *    处理单值查询结果,执行的select语句后,结果集只有1个
	 */
	@Test 
	public void demo03() throws SQLException{
		// ScalarHandler : 用于处理聚合函数执行结果(一行一列)
		// * 查询总记录数
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		String sql = "select count(*) from product";
		
		Object obj = queryRunner.query(sql, new ScalarHandler<Object>());
		
		System.out.println(obj.getClass());
		System.out.println(obj);
	}

运行结果:

class java.lang.Long
14

有此可以知道返回的是Long类型的,所以上述代码可以把两个Object改成Long,即:

/*
	 * 查询数据表结果集处理其中一种方式:
	 *    ScalarHandler处理方式
	 *    处理单值查询结果,执行的select语句后,结果集只有1个
	 */
	@Test 
	public void demo03() throws SQLException{
		// ScalarHandler : 用于处理聚合函数执行结果(一行一列)
		// * 查询总记录数
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		String sql = "select count(*) from product";
		
		Long obj = queryRunner.query(sql, new ScalarHandler<Long>());
		
		//System.out.println(obj.getClass());
		System.out.println(obj);
	}


1.5.5MapHandler

/*
	 * 查询数据表结果集处理其中一种方式:
	 *   MapHandler处理方式
	 *     将数据表结果集的第一行数据,封装成Map集合
	 *   键: 数据表中的列
	 *   值: 这个列中的数据
	 *   
	 *   处理方式的Map集合,是LinkedHashMap的子类
	 */
	@Test 
	public void demo04() throws SQLException{
		// MapHandler : 将查询到的一条记录,封装到Map中,map.key=字段名,map.value=值
		// * 主要用途:多表操作、将数据转换json 等
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		String sql = "select * from product where pid = ?";
		Object[] params = {6};
		Map<String,Object> map = queryRunner.query(sql, new MapHandler(), params);
		
		System.out.println(map);
	}

运行结果:

{pid=6, pname=花花公子, price=440.0, category_id=c002}


1.5.6MapListHandler

/*
	 * 查询数据表结果集其中一种处理方式:
	 *   MapListHandler处理方式
	 *     将数据表的结果集的每一行封装成Map集合
	 *     数据表多行数据,出现多个Map集合,存储List集合
	 */
	@Test 
	public void demo05() throws SQLException{
		// MapListHandler : 查询所有数据,将每一条记录封装到Map中,然后将Map添加到List中,最后返回List
		// * 主要用途:多表操作 等
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		String sql = "select * from product";
		List<Map<String,Object>> list = queryRunner.query(sql, new MapListHandler());
		
		for(Map<String,Object> map : list){
			System.out.println(map);
		}
		
	}

运行结果:

{pid=1, pname=联想, price=5000.0, category_id=c001}
{pid=2, pname=海尔, price=3000.0, category_id=c001}
{pid=3, pname=雷神, price=5000.0, category_id=c001}
{pid=4, pname=JACK JONES, price=800.0, category_id=c002}
{pid=5, pname=真维斯, price=200.0, category_id=c002}
{pid=6, pname=花花公子, price=440.0, category_id=c002}
{pid=7, pname=劲霸, price=2000.0, category_id=c002}
{pid=8, pname=香奈儿, price=800.0, category_id=c003}
{pid=9, pname=相宜本草, price=200.0, category_id=c003}
{pid=10, pname=面霸, price=5.0, category_id=c003}
{pid=11, pname=好想你枣, price=56.0, category_id=c004}
{pid=12, pname=香飘飘奶茶, price=1.0, category_id=c005}
{pid=13, pname=芒果99, price=998.0, category_id=c009}
{pid=990, pname=测试, price=100.0, category_id=c009}


1.5.7ArrayHandler

/*
	 *  查询数据表结果集处理其中一种方式:
	 *  ArrayHandler处理方式
	 *    将数据表中的第一行数据,存储到对象数组Object[]中
	 *  
	 *  注意: 获取查询后的第一行数据,如果查询不到结果集,返回的对象数组的length=0
	 */
	@Test 
	public void demo06() throws SQLException{
		// ArrayHandler :查询一条记录,将数据封装到数组中
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		String sql = "select * from product where pid = ?";
		Object[] params = {6};
		Object[] arr = queryRunner.query(sql, new ArrayHandler(), params);
		
		System.out.println(arr);
		System.out.println(Arrays.toString(arr));
	}

运行结果:

[Ljava.lang.Object;@42d3bd8b
[6, 花花公子, 440.0, c002]



1.5.8ArrayListHandler

/*
	 * 查询数据表结果集处理其中一种方式:
	 * ArrayListHandler处理方式
	 *  将数据表中的每一行数据,存储到一个对象数组Object[]中
	 *  而数据表中会有多行数据,产生多个对象数组, 存储到List集合中
	 */
	@Test 
	public void demo07() throws SQLException{
		// ArrayListHandler :查询所有,将每一条记录封装到数组中,然后添加到List,最后返回list
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		String sql = "select * from product";
		List<Object[]> list = queryRunner.query(sql, new ArrayListHandler());

		for(Object[] arr : list){
			System.out.println(Arrays.toString(arr));
		}
	}

运行结果:

[1, 联想, 5000.0, c001]
[2, 海尔, 3000.0, c001]
[3, 雷神, 5000.0, c001]
[4, JACK JONES, 800.0, c002]
[5, 真维斯, 200.0, c002]
[6, 花花公子, 440.0, c002]
[7, 劲霸, 2000.0, c002]
[8, 香奈儿, 800.0, c003]
[9, 相宜本草, 200.0, c003]
[10, 面霸, 5.0, c003]
[11, 好想你枣, 56.0, c004]
[12, 香飘飘奶茶, 1.0, c005]
[13, 芒果99, 998.0, c009]
[990, 测试, 100.0, c009]


1.5.9KeyedHandler

@Test 
	public void demo08() throws SQLException{
		// KeyedHandler : new KeyedHandler("字段名称"),查询所有,将查询结果封装到Map中
		// * map.key=为指定“字段名称”对应的值
		// * map.value=为当前整条记录所有的值,数据为Map<字段名,值>
		// 类型  Map<String , Map<String,Object> >
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		String sql = "select * from product";
		Map<String,Map<String,Object>> map = queryRunner.query(sql, new KeyedHandler<String>("pname"));

		for(Map.Entry<String, Map<String,Object>> entry : map.entrySet()){
			System.out.println(entry.getKey());
			System.out.println(entry.getValue());
		}
		
	}

运行结果:

香飘飘奶茶
{pid=12, pname=香飘飘奶茶, price=1.0, category_id=c005}
面霸
{pid=10, pname=面霸, price=5.0, category_id=c003}
测试
{pid=990, pname=测试, price=100.0, category_id=c009}
劲霸
{pid=7, pname=劲霸, price=2000.0, category_id=c002}
联想
{pid=1, pname=联想, price=5000.0, category_id=c001}
海尔
{pid=2, pname=海尔, price=3000.0, category_id=c001}
真维斯
{pid=5, pname=真维斯, price=200.0, category_id=c002}
雷神
{pid=3, pname=雷神, price=5000.0, category_id=c001}
芒果99
{pid=13, pname=芒果99, price=998.0, category_id=c009}
相宜本草
{pid=9, pname=相宜本草, price=200.0, category_id=c003}
JACK JONES
{pid=4, pname=JACK JONES, price=800.0, category_id=c002}
花花公子
{pid=6, pname=花花公子, price=440.0, category_id=c002}
好想你枣
{pid=11, pname=好想你枣, price=56.0, category_id=c004}
香奈儿
{pid=8, pname=香奈儿, price=800.0, category_id=c003}


1.5.10ColumnListHandler

/*
	 * 查询数据表结果集处理其中一种方式:
	 *   ColumnListHandler处理方式
	 *     将查询数据表结果集中的某一列数据,存储到List集合
	 *     哪个列不清楚,数据类型也不清楚, List<Object>
	 *  ColumnListHandler构造方法
	 *    空参数: 获取就是数据表的第一列
	 *    int参数: 传递列的顺序编号
	 *    String参数: 传递列名
	 *    
	 *  创建对象,可以加入泛型,但是加入的数据类型,要和查询的列类型一致
	 */
	@Test 
	public void demo09() throws SQLException{
		// ColumnListHandler : 查询指定一列数据
		QueryRunner queryRunner = new QueryRunner(C3P0Utils.getDataSource());
		String sql = "select * from product";
		List<String> list = queryRunner.query(sql, new ColumnListHandler<String>("pname"));

		System.out.println(list);
	}

运行结果:

[联想, 海尔, 雷神, JACK JONES, 真维斯, 花花公子, 劲霸, 香奈儿, 相宜本草, 面霸, 好想你枣, 香飘飘奶茶, 芒果99, 测试]


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值