DBUtils实现CRUD操作
API介绍:
-
org.apache.commons.dbutils.QueryRunner
-
org.apache.commons.dbutils.ResultSetHandler
-
工具类:org.apache.commons.dbutils.DbUtils
-
QueryRunner提供数据库操作的一系列重载的update()和query()操作
-
QueryRunner类提供了两个构造器:
默认的构造器
需要一个 javax.sql.DataSource 来作参数的构造器 -
ResultSetHandler接口用于处理数据库查询操作得到的结果集。不同的结果集的情形,由其不同的子类实现
1.添加
方式一:向数据表中添加一条记录
@Test
public void test1() {
Connection connection = null;
try {
//1. 先获取数据库的连接 调用工具类
connection = JDBCUtils.getConnection();
//2. 提供一个添加操作的sql
String sql = "insert into customers(name,email,birth)values('王海','tom@126.com','2020-09-08')";
//3. 使用提供好的QueryRunner,调用update()方法,实现数据的插入
QueryRunner runner = new QueryRunner();
int count = runner.update(connection, sql);
System.out.println("添加了" + count + "条记录");
} catch (Exception e) {
e.printStackTrace();
} finally {
//4. 资源的关闭
JDBCUtils.close(connection);
}
}
方式二:使用带占位符的sql 比较推荐 共用一个sql 大文件用 insert一次一条
@Test
public void test2() {
Connection connection = null;
try {
//1. 先获取数据库的连接
connection = JDBCUtils.getConnection();
//2. 提供一个包含占位符的sql '?'就是占位符
//String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)";
String sql = "insert into customers(name,email,birth)values(?,?,?)";
//3. 使用提供好的QueryRunner,调用update()方法,实现数据的插入
QueryRunner runner = new QueryRunner();
//有几个占位符添加几个参数
int count = runner.update(connection, sql,"丸子","wanzi@163.com","2021-10-5");
//int count = runner.update(connection, sql,"丸子","wanzi@163.com",new Date(23423423432423L));
System.out.println("添加了" + count + "条记录");
} catch (Exception e) {
e.printStackTrace();
} finally {
//4. 资源的关闭
JDBCUtils.close(connection);
}
}
2.删除(使用占位符)
//删除记录的操作 自带批量
@Test
public void test3(){
Connection connection = null;
try {
//1. 先获取数据库的连接
connection = JDBCUtils.getConnection();
//2. 提供一个包含占位符的sql
String sql = "delete from customers where id > ?";
//3. 使用提供好的QueryRunner,调用update()方法,实现数据的插入
QueryRunner runner = new QueryRunner();
//params:19填充占位符
int count = runner.update(connection, sql,19);
System.out.println("删除了" + count + "条记录");
} catch (Exception e) {
e.printStackTrace();
} finally {
//4. 资源的关闭
JDBCUtils.close(connection);
}
}
3.修改
//修改表数据的操作 自带批量
@Test
public void test4(){
Connection connection = null;
try {
//1. 先获取数据库的连接
connection = JDBCUtils.getConnection();
//2. 提供一个包含占位符的sql
String sql = "update customers set email = ? where id = ?";
//3. 使用提供好的QueryRunner,调用update()方法,实现数据的插入
QueryRunner runner = new QueryRunner();
//params填充占位符
int count = runner.update(connection, sql,"tom@gmail.com",19);
System.out.println("修改了" + count + "条记录");
} catch (Exception e) {
e.printStackTrace();
} finally {
//4. 资源的关闭
JDBCUtils.close(connection);
}
}
4.查询
ResultSetHandler接口的主要实现类:
- BeanHandler:对应查询表中的一条记录,以对象的方式返回
- BeanListHandler:对应查询表中的多条记录,以对象构成的集合的方式返回
- MapHandler:对应查询表中的一条记录,结果集ResultSetHandler<Map<String,Object>>里的数据以map对象的方式返回。
map中key为表中的字段名,map中value为表中一条数据的数据值。 - MapListHandler:对应查询表中的多条记录,以map对象构成的List的方式返回。ResultSetHandler<List<Map<String, Object>>> 。按map中的key排序
map中key为表中的字段名,map中value为表中一条数据的数据值。 - ScalarHandler:用于查询表中的特殊值。比如:count(*) \ max(xxx)
query源码:
ResultSetHandler<T> rsh
表示结果集
public <T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params) throws SQLException {
PreparedStatement stmt = null;
ResultSet rs = null;
Object result = null;
try {
stmt = this.prepareStatement(conn, sql);
this.fillStatement(stmt, params);
rs = this.wrap(stmt.executeQuery());
result = rsh.handle(rs);
} catch (SQLException var33) {
this.rethrow(var33, sql, params);
} finally {
try {
this.close(rs);
} finally {
this.close((Statement)stmt);
}
}
return result;
}
BeanHandler源码:
public class BeanHandler<T> implements ResultSetHandler<T> {
private final Class<T> type;
private final RowProcessor convert;
public BeanHandler(Class<T> type) {
this(type, ArrayHandler.ROW_PROCESSOR);
}
public BeanHandler(Class<T> type, RowProcessor convert) {
this.type = type;
this.convert = convert;
}
public T handle(ResultSet rs) throws SQLException {
return rs.next() ? this.convert.toBean(rs, this.type) : null;
}
}
测试数据表的查询操作,返回结果集:
public class QueryTest {
/*
* BeanHandler:对应查询表中的一条记录,以对象的方式返回
*
* */
@Test
public void test1() {
Connection connection = null;
try {
//1.获取数据库的连接
connection = JDBCUtils.getConnection();
//2.提供一条带占位符的查询语句sql
String sql = "select id,name,email,birth from customers where id = ?";
//3. 创建QueryRunner的实例
QueryRunner runner = new QueryRunner();
//4. 通过QueryRunner的实例,调用其query() BeanHandler
BeanHandler<Customer> handler = new BeanHandler<>(Customer.class);
Customer customer = runner.query(connection, sql, handler, 1);
System.out.println(customer);
} catch (Exception e) {
e.printStackTrace();
} finally {
//5. 关闭资源
JDBCUtils.close(connection);
}
}
/*
* BeanListHandler:对应查询表中的多条记录,以对象构成的集合的方式返回
*
* */
@Test
public void test2() {
Connection connection = null;
try {
//1.获取数据库的连接
connection = JDBCUtils.getConnection();
//2.提供一条带占位符的查询语句sql
String sql = "select id,name,email,birth from customers where id > ?";
//3. 创建QueryRunner的实例
QueryRunner runner = new QueryRunner();
//4. 通过QueryRunner的实例,调用其query() BeanListHandler---- ResultSetHandler<List>
//BeanListHandler<Customer> handler = new BeanListHandler<>(Customer.class);
ResultSetHandler<List<Customer>> handler = new BeanListHandler<>(Customer.class);
List<Customer> list = runner.query(connection, sql, handler, 1);
list.forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
} finally {
//5. 关闭资源
JDBCUtils.close(connection);
}
}
/*
* MapHandler:对应查询表中的一条记录,结果集ResultSetHandler<Map<String,Object>>里数据以map对象的方式返回。
* map中key为表中的字段名,map中value为表中一条数据的数据值。
*
* */
@Test
public void test3() {
Connection connection = null;
try {
//1.获取数据库的连接
connection = JDBCUtils.getConnection();
//2.提供一条带占位符的查询语句sql
String sql = "select id,name,email,birth from customers where id = ?";
//3. 创建QueryRunner的实例
QueryRunner runner = new QueryRunner();
//4. 通过QueryRunner的实例,调用其query()
//MapHandler handler = new MapHandler();
//结果集 Map<String,Object>
ResultSetHandler<Map<String,Object>> handler = new MapHandler();
Map<String, Object> map = runner.query(connection, sql, handler, 1);
System.out.println(map);
} catch (Exception e) {
e.printStackTrace();
} finally {
//5. 关闭资源
JDBCUtils.close(connection);
}
}
/*
* MapListHandler:对应查询表中的多条记录,以map对象构成的List的方式返回。ResultSetHandler<List<Map<String, Object>>>
* 按map中的key排序
* map中key为表中的字段名,map中value为表中一条数据的数据值。
*
* */
@Test
public void test4() {
Connection connection = null;
try {
//1.获取数据库的连接
connection = JDBCUtils.getConnection();
//2.提供一条带占位符的查询语句sql
String sql = "select id,name,email,birth from customers where id > ?";
//3. 创建QueryRunner的实例
QueryRunner runner = new QueryRunner();
//4. 通过QueryRunner的实例,调用其query()
ResultSetHandler<List<Map<String, Object>>> handler = new MapListHandler();
List<Map<String, Object>> list = runner.query(connection, sql, handler, 1);
list.forEach(System.out::println);
} catch (Exception e) {
e.printStackTrace();
} finally {
//5. 关闭资源
JDBCUtils.close(connection);
}
}
/*
* ScalarHandler:用于查询表中的特殊值。比如:count(*) \ max(xxx)
*
* */
@Test
public void test5(){
Connection connection = null;
try {
//1.获取数据库的连接
connection = JDBCUtils.getConnection();
//2.提供一条带占位符的查询语句sql
String sql = "select count(*) from customers";
//3. 创建QueryRunner的实例
QueryRunner runner = new QueryRunner();
//4. 通过QueryRunner的实例,调用其query()
ScalarHandler handler = new ScalarHandler();
long count = (long) runner.query(connection, sql, handler);
System.out.println("查询到表中一共有" + count + "条记录");
} catch (Exception e) {
e.printStackTrace();
} finally {
//5. 关闭资源
JDBCUtils.close(connection);
}
}
@Test
public void test6(){
Connection connection = null;
try {
//1.获取数据库的连接
connection = JDBCUtils.getConnection();
//2.提供一条带占位符的查询语句sql
String sql = "select max(birth) from customers";
//3. 创建QueryRunner的实例
QueryRunner runner = new QueryRunner();
//4. 通过QueryRunner的实例,调用其query()
ScalarHandler handler = new ScalarHandler();
Date birth = (Date) runner.query(connection, sql, handler);
System.out.println("查询到表中最大的birth是:" + birth);
} catch (Exception e) {
e.printStackTrace();
} finally {
//5. 关闭资源
JDBCUtils.close(connection);
}
}
}
SELECT id,NAME,email,birth FROM customers WHERE id = 1;
sql查询结果集如下👇
对应test1运行,查询一条数据结果如下:
查询多条数据结果如下:
以map对象的方式返回:
以List<Map<String, Object>>的方式返回结果集如下:
test5运行结果如下:
ORM(object relational mapping)编程思想:
- 数据库中的一个表 与 Java中的一个类对应
- 表中的一条记录 与 类中一个对象对应
- 表中的一个列(或字段) 与 类中的一个属性对应
public class Customer {
private int id;
private String name;
private String email;
private Date birth;
// private Blob photo;
@Override
public String toString() {
return "Customer{" +
"id=" + id +
", name='" + name + '\'' +
", email='" + email + '\'' +
", birth=" + birth +
'}';
}
public Customer(int id, String name, String email, Date birth) {
this.id = id;
this.name = name;
this.email = email;
this.birth = birth;
}
public Customer() {
}
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 String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getBirth() {
return birth;
}
public void setBirth(Date birth) {
this.birth = birth;
}
}
如果表中的字段名与类中的属性名不一致,为了查询操作结果的准确性,我们需要编写sql时,使用类的属性名作为select后字段的别名出现。
👇
SELECT order_id,order_name,order_date FROM `order` WHERE order_id = 1;
SELECT order_id orderId,order_name orderName,order_date orderDate FROM `order` WHERE order_id =1;
代码如下:
public class QueryTest {
/*
* 查询order表中的一条记录,返回Order类的一个对象
*
* */
@Test
public void test1() throws Exception {
//3个参数
Connection connection = JDBCUtils.getConnection();
//SELECT order_id orderId,order_name orderName,order_date orderDate FROM `order` WHERE order_id = ? 起别名
//使列名和java中的属性名一致
String sql = "SELECT order_id orderId,order_name orderName,order_date orderDate FROM `order` WHERE order_id = ?";
BeanHandler<Order> handler = new BeanHandler<>(Order.class);
//核心代码
QueryRunner runner = new QueryRunner();
Order order = runner.query(connection, sql, handler, 1);
System.out.println(order);
}
}