DBUtils工具类
使用JDBC我们发现冗余的代码太多了,为了简化开发 我们选择使用 DbUtils。Commons DbUtils是Apache组织提供的一个对JDBC进行简单封装的开源工具类库,使用它能够简化JDBC应用程序的开发,同时也不会影响程序的性能。
1. 使用方式
DBUtils就是JDBC的简化开发工具包。需要项目导入 commons-dbutils-1.6.jar
2. Dbutils核心功能介绍
- QueryRunner 中提供对sql语句操作的API
- ResultSetHandler接口,用于定义select操作后,怎样封装结果集
- DbUtils类,他就是一个工具类,定义了关闭资源与事务处理相关方法
3. 表和类之间的关系
- 整个表可以看做是一个类
- 表中的一行记录,对应一个类的实例(对象)
- 表中的一列,对应类中的一个成员属性
4. JavaBean组件
JavaBean 就是一个类, 开发中通常用于封装数据,有一下特点:
- 需要实现 序列化接口, Serializable
- 提供私有字段: private 类型 变量名
- 提 供 getter 和 setter
JavaBean代码示例:
package com.lagou.entity;
import java.io.Serializable;
import java.util.Date;
/**
* JavaBean类
* 用来存储数据 成员变量私有 提供get set 提供空参 实现序列化接口
*
* Employee类 就是对应了 数据库中Employee表
* `eid` INT(11) NOT NULL AUTO_INCREMENT,
* `ename` VARCHAR(20) DEFAULT NULL,
* `age` INT(11) DEFAULT NULL,
* `sex` VARCHAR(6) DEFAULT NULL,
* `salary` DOUBLE DEFAULT NULL,
* `empdate` DATE DEFAULT NULL,
*
*/
public class Employee implements Serializable {
//成员变量的名称 与 表中的列要一样
private int eid;
private String ename;
private int age;
private String sex;
private double salary;
private Date empdate;
public Employee() {
}
public Employee(int eid, String ename, int age, String sex, double salary, Date empdate) {
this.eid = eid;
this.ename = ename;
this.age = age;
this.sex = sex;
this.salary = salary;
this.empdate = empdate;
}
public int getEid() {
return eid;
}
public void setEid(int eid) {
this.eid = eid;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public Date getEmpdate() {
return empdate;
}
public void setEmpdate(Date empdate) {
this.empdate = empdate;
}
@Override
public String toString() {
return "Employee{" +
"eid=" + eid +
", ename='" + ename + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
", salary=" + salary +
", empdate=" + empdate +
'}';
}
}
QueryRunner类介绍
1. QueryRunner创建
- 手动模式:QueryRunner qr = new QueryRunner();
- 自动模式:QueryRunner qr2 = new QueryRunner(DruidUtils.getDataSource());
- 自动模式需要传入连接池的对象:
public static DataSource getDataSource(){
return dataSource;
}
2. QueryRunner实现增、删、改操作
- 核心方法:update(Connection conn, String sql, Object... params)
- 形参说明:
参数 | 说明 |
Connection conn | 数据库连接对象, 自动模式创建QueryRun 可以不传 ,手动模式必须传递 |
String sql | 占位符形式的SQL ,使用 ? 号占位符 |
Object... param | Object类型的 可变参,用来设置占位符上的参数 |
- 步骤:
1)创建QueryRunner(手动或自动)
2)占位符方式 编写SQL
3)设置占位符参数
4)执行
QueryRunner增、删、改代码示例:
package com.lagou.testDBUtils;
import com.lagou.utils.DBCPUtils;
import com.lagou.utils.DruidUtils;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.junit.Test;
import java.sql.Connection;
import java.sql.SQLException;
/*
* 使用QueryRunner对象 完成增删改
* update(Connection con,String sql,Object... param) 方法
*
* */
public class DBUtilsDemo02 {
//插入操作
@Test
public void testInsert() throws SQLException {
//1.创建 QueryRunner 手动模式创建
QueryRunner qr = new QueryRunner();
//2.编写 占位符方式 SQL
String sql = "insert into employee values(?,?,?,?,?,?)";
//3.设置占位符的参数
Object[] param = {null,"张百万",20,"女",10000,"1990-12-26"};
//4.执行 update方法
Connection con = DruidUtils.getConnection();
int i = qr.update(con, sql, param);
//5.释放资源
DbUtils.closeQuietly(con);
}
//修改操作 修改姓名为 张百万的员工的工资为 15000
@Test
public void testUpdate() throws SQLException {
//1.创建 核心类 自动模式 需要传递 数据库连接池对象
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
//2.编写SQl
String sql = "update employee set salary = ? where ename = ?";
//3.设置占位符的参数
Object[] param = {15000,"张百万"};
//4.执行修改操作 自动模式不需要传入connection对象
qr.update(sql,param);
}
//删除操作 删除id为1的 记录
@Test
public void testDelete() throws SQLException {
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
String sql = "delete from employee where eid = ?";
//如果只有一个参数的话 不需要创建数组
qr.update(sql,1);
}
}
3. QueryRunner实现查询操作
1)ResultSetHandler接口可以对查询出来的ResultSet结果集进行处理,达到一些业务上的需求
以下是ResultSetHandler几个常见的实现类,每一种实现类都代表了对查询结果集的一种处理方式:
ResultSetHandler 实现类 | 说明 |
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 表操作。 |
2)QueryRunner的查询方法
query方法的返回值都是泛型,具体的返回值类型,会根据结果集的处理方式,发生变化
方法 | 说明 |
query(String sql, handler ,Object[] param) | 自动模式创建QueryRunner, 执行查询<b |
query(Connection con,String sql,handler,Object[] param) | 手动模式创建QueryRunner, 执行查询 |
ResultSetHandler几个常见的实现类代码示例:
package com.lagou.testDBUtils;
import com.lagou.entity.Employee;
import com.lagou.utils.DruidUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.*;
import org.junit.Test;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class DBUtilsDemo03 {
/*
* 查询id为5的记录,封装到数组中
* ArrayHandler 将结果集的第一条数据封装到数组中
* */
@Test
public void testFindById() throws SQLException {
//1.创建QueryRunner
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
//2.编写SQL
String sql = "select * from employee where eid = ?";
//3.执行查询
Object[] query = qr.query(sql, new ArrayHandler(), 5);
//4.获取数据
System.out.println(Arrays.toString(query));
}
/**
* 查询所有数据,封装到List集合中
* ArrayListHandler可以将每条数据先封装到数组中, 再将数组封装到集合中
*
*/
@Test
public void testFindAll() throws SQLException {
//1.创建QueryRunner
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
//2.编写SQL
String sql = "select * from employee";
//3.执行查询
List<Object[]> query = qr.query(sql, new ArrayListHandler());
//4.遍历集合获取数据
for (Object[] objects : query) {
System.out.println(Arrays.toString(objects));
}
}
/**
* 查询id为3的记录,封装到指定JavaBean中
* BeanHandler 将结果集的第一条数据封装到 javaBean中
*
**/
@Test
public void testFindByIdJavaBean() throws SQLException {
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
String sql = "select * from employee where eid = ?";
Employee employee = qr.query(sql, new BeanHandler<Employee>(Employee.class), 3);
System.out.println(employee);
}
/*
* 查询薪资大于 3000 的所员工信息,封装到JavaBean中再封装到List集合中
* BeanListHandler 将结果集的每一条和数据封装到 JavaBean中 再将JavaBean 放到list集合中
* */
@Test
public void testFindBySalary() throws SQLException {
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
String sql = "select * from employee where salary > ?";
List<Employee> list = qr.query(sql, new BeanListHandler<Employee>(Employee.class), 3000);
for (Employee employee : list) {
System.out.println(employee);
}
}
/*
* 查询姓名是 张百万的员工信息,将结果封装到Map集合中
* MapHandler 将结果集的第一条记录封装到 Map<String,Object>中
* key对应的是 列名 value对应的是 列的值
* */
@Test
public void testFindByName() throws SQLException {
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
String sql = "select * from employee where ename = ?";
Map<String, Object> map = qr.query(sql, new MapHandler(), "张百万");
Set<Map.Entry<String, Object>> entries = map.entrySet();
for (Map.Entry<String, Object> entry : entries) {
//打印结果
System.out.println(entry.getKey() +" = " +entry.getValue());
}
}
/*
* 查询所有员工的薪资总额
* ScalarHandler 用于封装单个的数据
* */
@Test
public void testGetSum() throws SQLException {
QueryRunner qr = new QueryRunner(DruidUtils.getDataSource());
String sql = "select sum(salary) from employee";
Double sum = (Double)qr.query(sql, new ScalarHandler<>());
System.out.println("员工薪资总额: " + sum);
}
}
节选自拉钩教育JAVA系列教程