JavaWEB-(十二)Apache的DbUtils框架

本文最后更新于:December 3, 2021 pm

commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jdbc编码的工作量,同时也不会影响程序的性能。DbUtils是java编程中数据库操作实用小工具,小巧、简单、实用。对于数据表的查询操作,可以把结果转换为 List 、Array 、Set 等集合便于操作。而对于数据表的DML操作,也只需要写SQL语句即可。

目录

1.commons-dbutils简介

1.1 QueryRunner类使用

该类简单化了SQL查询,它与ResultSetHandler组合在一起使用可以完成大部分的数据库操作,能够大大减少编码量。

主要方法

  • 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:用来执行一个不需要置换参数的更新操作。

1.2 ResultSetHandler接口使用

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

实现类

  • ArrayHandler:把结果集中的第一行数据转成对象数组。
  • ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
  • BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
  • BeanListHandler:将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
  • ColumnListHandler:将结果集中某一列的数据存放到List中。
  • KeyedHandler(name):将结果集中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。
  • MapHandler:将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
  • MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List

2.准备工作

2.1 导包

  • MySQL连接驱动 jar 包。
  • Druid-1.1.22.jar
  • commons-dbutils-1.7.jar
  • database.properties配置文件

2.2 主要使用

ResultSetHandler接口:转换类型接口

  • BeanHandler类:实现类,把一条记录转换成对象。
  • BeanListHandler类:实现类,把多条记录转换成List集合。
  • ScalarHandler类:实现类,适合获取一行一列的数据。封装的long类型的,而不是int。

QueryRunner:执行SQL语句的类

  • 增、删、改:update();
  • 查询:query();

3.代码实现

3.1 基本代码

  1. db.properties
1
2
3
4
5
6
7
8
9
10
11
12
13
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/WeekDay?serverTimezone=GMT%2B8
username=root
password=loong461
# Druid连接池=======================================
# 初始化连接数量
initialSize=10
# 最大连接数量,当初始化的用完时,就继续新建
maxActive=30
# 最小空闲连接数量,即连初始化的都长时间没有用时,也会将其释放,直至最小空闲连接数量
minIdle=5
# 超时等待时间,以毫秒为单位。如果有超过最大连接数量的需求,则超过部分需要等待相应的时间,如果超了等待时间,就不会再等,即拿不到连接。
maxWait=5000
  1. DbUtils

在原代码上需要添加一个新方法,用来获取连接池:

1
2
3
public static DataSource getDataSource(){
return dds;
}

完整代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package com.tothefor.OtherTest.Duid.Utils;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.pool.DruidDataSourceFactory;

import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
* @Author DragonOne
* @Date 2021/8/14 23:33
*/
public class DbUtils {
//声明连接池对象
private static DruidDataSource dds;
static{
Properties properties = new Properties();
InputStream is = DbUtils.class.getResourceAsStream("/db.properties");
try {
properties.load(is);
//创建连接池
dds = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}

public static Connection getConnection() {
try {
return dds.getConnection();//通过连接池获取连接对象
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}

public static DataSource getDataSource(){
return dds;
}

public static void closeAll(Connection connection, Statement statement, ResultSet resultSet){
try {
if(resultSet != null){
resultSet.close();
}
if(statement != null){
statement.close();
}
if(connection != null){
connection.close();
}
}catch (SQLException e){
e.printStackTrace();
}
}
}

  1. entity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package com.tothefor.OtherTest.ApacheDbUtils.entity;

/**
* @Author DragonOne
* @Date 2021/8/15 22:09
*/
public class Person {
private int id;
private String name;
private int money;

public Person(int id, String name, int money) {
this.id = id;
this.name = name;
this.money = money;
}

public Person() {
}

public int getId() {
return id;
}

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

public String getName() {
return name;
}

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

public int getMoney() {
return money;
}

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

@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
", money=" + money +
'}';
}
}

  1. Dao及其Impl

这里只实现了增加方法(addPerson)的代码,删除、修改的实现同理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package com.tothefor.OtherTest.ApacheDbUtils.Dao;

import com.tothefor.OtherTest.ApacheDbUtils.entity.Person;

import java.util.List;

/**
* @Author DragonOne
* @Date 2021/8/15 22:17
*/
public interface PersonDao {
public int addPerson(Person person);
public int delPerson(String name);
public Person queryPerson(String name); //查询单个
public List<Person> queryAll(); //查询全部
}


//Dao实现类
package com.tothefor.OtherTest.ApacheDbUtils.Dao.Impl;

import com.tothefor.OtherTest.ApacheDbUtils.Dao.PersonDao;
import com.tothefor.OtherTest.ApacheDbUtils.entity.Person;
import com.tothefor.OtherTest.Duid.Utils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;

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

/**
* @Author DragonOne
* @Date 2021/8/15 22:28
*/
public class PersonDaoImpl implements PersonDao {
private QueryRunner queryRunner = new QueryRunner(DbUtils.getDataSource());//需要使用有参数的,也可以使用不带参数的,根据需求进行选择。
@Override
public int addPerson(Person person) {
Object[] params = {person.getId(),person.getName(),person.getMoney()}; //参数列表
try {
int result = queryRunner.update("insert into Te(id,name,money) values (?,?,?)",params);
return result;
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}

@Override
public int delPerson(String name) {
return 0;
}

@Override
public Person queryPerson(String name) {
/* 当QueryRunner使用的是没有参数时,就在需要的时候再创建连接,如下:
Person person = queryRunner.query(DbUtils.getConnection(),"select * from Person where string=?",name); //这里没有添加异常,自行添加即可。
*/
return null;
}

@Override
public List<Person> queryAll() {
return null;
}
}


  1. 查询实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//单个查询
@Override
public Person queryPerson(String name) {
try {
Person man = queryRunner.query("select * from Te where name = ?",new BeanHandler<Person>(Person.class),name);
return man;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}


//查询全部
@Override
public List<Person> queryAll() {
try {
List<Person> personList = queryRunner.query("select * from Te ", new BeanListHandler<Person>(Person.class));
return personList;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
  1. 测试代码

增加方法的测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.tothefor.OtherTest.ApacheDbUtils.Test;

import com.tothefor.OtherTest.ApacheDbUtils.Dao.Impl.PersonDaoImpl;
import com.tothefor.OtherTest.ApacheDbUtils.Dao.PersonDao;
import com.tothefor.OtherTest.ApacheDbUtils.entity.Person;

/**
* @Author DragonOne
* @Date 2021/8/15 22:40
*/
public class ApacheUtilsTest {
public static void main(String[] args){
PersonDao personDao = new PersonDaoImpl();
Person person = new Person(4231,"tewt",234);
int t = personDao.addPerson(person);
System.out.println(t); //1
}
}

查询方法的测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//查询单个==================================
public static void main(String[] args){
PersonDao personDao = new PersonDaoImpl();
Person person = personDao.queryPerson("loong");
System.out.println(person);

}

//输出
Person{id=234, name='loong', money=234}


//查询全部==================================
public static void main(String[] args){
PersonDao personDao = new PersonDaoImpl();
List<Person> lps= personDao.queryAll();
for(Person p : lps){
System.out.println(p);
}

}

//输出
Person{id=123, name='qqewr', money=34}
Person{id=234, name='loong', money=234}
Person{id=423, name='wer', money=54}
Person{id=434, name='qqewr', money=34}
Person{id=908, name='qqewr', money=34}
Person{id=4231, name='tewt', money=234}
Person{id=4234, name='qqewr', money=34}
Person{id=4349, name='qqewr', money=34}
Person{id=42234, name='qqewr', money=34}
Person{id=422234, name='qqewr', money=34}

4.ScalarHandler类的应用

在Dao层中新增 public long querySum();方法,用来查询总个数。实现类中具体实现代码:

1
2
3
4
5
6
7
8
9
10
@Override
public long querySum() { //返回值需要为long,不能为int
try {
long PersonSum = queryRunner.query("select count(*) from Te",new ScalarHandler<>());
return PersonSum;
} catch (SQLException e) {
e.printStackTrace();
}
return 0;
}

测试代码:

1
2
3
4
5
public static void main(String[] args){
PersonDao personDao = new PersonDaoImpl();
System.out.println(personDao.querySum()); //10,可见上面查询结果

}