在“【JDBC】JDBC的基本使用步骤”一文中,我讲解了JDBC中最原始的执行SQL(Satement或PreparedStatement)以及获取执行结果(ResultSet)的相关API用法。接下来,我将讲解一个工具(DBUtils),它能够极大地简化我们在Java中执行SQL的代码量。
注意:DBUtils并不是一项新的技术,它只是把原始技术中的Satement、PreparedStatement、ResultSet等做了一个封装,让我们直接调用它。
Table of Contents
ArrayHandler和ArrayListHandler类使用
BeanHandler和BeanListHandler类的用法
ColumnListHandler类使用ScalarHandler类使用
初识DBUtils
诞生背景:
- 如果只使用JDBC进行开发,我们会发现冗余代码过多,为了简化JDBC开发,本案例我们讲采用apache commons组件一个成员:DBUtils。
- DBUtils就是JDBC的简化开发工具包。需要项目导入commons-dbutils-1.6.jar才能够正常使用DBUtils工具。
优点:
- 无资源泄漏 - DBUtils类确保不会发生资源泄漏。
- 清理和清除代码 - DBUtils类提供干净清晰的代码来执行数据库操作,而无需编写任何清理或资源泄漏防护代码。防止了SQL注入。
- Bean映射 - DBUtils类支持从结果集中自动填充Java Bean。
特性:
- DBUtils是java编程中的数据库操作实用工具,小巧简单实用。
- DBUtils封装了对JDBC的操作,简化了JDBC操作,可以少写代码。
- Dbutils三个核心功能介绍:
- QueryRunner中提供对sql语句操作的API
- ResultSetHandler接口,用于定义select操作后,怎样封装结果集
- DbUtils类,它就是一个工具类,定义了关闭资源与事务处理的方法
准备一个SQL:
CREATE DATABASE mydb;
USE mydb;
CREATE TABLE person(
p_id INT PRIMARY KEY,
p_name VARCHAR(10),
p_age INT
);
INSERT INTO person(p_id,p_name,p_age) VALUES
(1,"asus",20),
(2,"alibaba",40),
(3,"huawei",50)
QueryRunner类
功能:包装并执行SQL语句
核心方法:
int update(Connection conn, String sql, Object... params)
,用来完成表数据的增加、删除、更新操作,返回执行成功后影响的行数。可变参数的出现是因为SQL语句中会出现占位符。<T> T query(Connection conn, String sql, ResultSetHandler<T> rsh, Object... params)
,用来完成表数据的查询操作,返回的是相关类型。T表示泛型。
Notice:update方法使用示例如下,query方法使用示例在ResultSetHandle接口的讲解中!
增、删、改方法使用示例
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
public class FirstApp {
//为了更加方便看到结果,这里直接使用这种方式连接数据库
static final String driver = "com.mysql.jdbc.Driver";
static final String url = "jdbc:mysql://localhost:3306/mydb";
static final String user = "root";
static final String passwd = "kyle";
public static void main(String[] args) throws SQLException {
Connection conn = null;
//Step 1: Register JDBC driver
DbUtils.loadDriver(driver);
//Step 2: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(url, user, passwd);
//注意:以下三个函数不能同时开启!
//insert(conn);
//update(conn);
delete(conn);
}
public static void insert(Connection conn) {
QueryRunner qr = new QueryRunner();
String sql = "INSERT INTO person (p_id,p_name,p_age) VALUES (?,?,?)";
Object[] params = {5,"apple",30};
int row = 0;
try {
row = qr.update(conn,sql,params);
System.out.println("受影响的行数为:" + row);
} catch (SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(conn);
}
}
public static void update(Connection conn) {
QueryRunner qr = new QueryRunner();
String sql = "UPDATE person SET p_name=?,p_age=? WHERE p_id=?";
//定义Object数组,存储?中的参数
Object[] params = {"huawei",200,1};
int row = 0;
try {
row = qr.update(conn,sql,params);
System.out.println("受影响的函数为:" + row);
} catch (SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(conn);
}
}
public static void delete(Connection conn) {
QueryRunner qr = new QueryRunner(); //创建SQL类对象
String sql = "DELETE FROM person WHERE p_id=?";
int row;
try {
row = qr.update(conn,sql,3); //参数:连接对象,要执行的SQL语句,SQL语句中各个问号的具体值
System.out.println("被影响的行数为:" + row);
} catch (SQLException e) {
e.printStackTrace();
} finally {
DbUtils.closeQuietly(conn);
}
}
}
ResultSetHandle接口
功能:接收并处理QueryRunner类的query方法执行结果!
接口实现类概览:
- ArrayHandler 将结果集中的第一条记录封装到一个Object[]数组中,数组中的每一个元素就是这条记录中的每一个字段的值
- ArrayListHandler 将结果集中的每一条记录都封装到一个Object[]数组中,将这些数组在封装到List集合中。
- BeanHandler 将结果集中第一条记录封装到一个指定的JavaBean中。
- BeanListHandler 将结果集中每一条记录封装到指定的JavaBean中,将这些JavaBean在封装到List集合中
- ColumnListHandler 将结果集中指定的列的字段值,放到一个List集合中
- ScalarHandler 应用于查询结果集中有且只有一个结果(仅一行一列)的情形
- MapHandler 将结果集第一行封装到Map集合中,Key 列名, Value 该列数据
- MapListHandler 将结果集所有行封装到Map集合中,Key 列名, Value 该列数据,Map集合存储到List集合
ArrayHandler和ArrayListHandler类使用
- ArrayHandler类功能:将结果集第一行存储到Object数组中
- ArrayListHandler类功能:将结果集全部存储到Object数组中
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
public class FirstApp {
static final String driver = "con.mysql.jdbc.Driver";
static final String url = "jdbc:mysql://localhost:3306/mydb";
static final String user = "root";
static final String passwd = "kyle";
public static void main(String[] args) throws SQLException {
Connection conn = null;
// Step 1: Register JDBC driver
DbUtils.loadDriver(driver);
// Step 2: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(url, user, passwd);
arrayListHandler(conn);
}
public static void arrayHandler(Connection conn)throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM person";
//调用方法query执行查询,传递连接对象,SQL语句,结果集处理方式的实现类
//返回对象数组
Object[] result = qr.query(conn, sql, new ArrayHandler());
for(Object obj : result){
System.out.print(obj + " ");
}
}
public static void arrayListHandler(Connection conn) throws SQLException {
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM person";
List<Object[]> result = qr.query(conn, sql,new ArrayListHandler());
for(Object[] objs:result) { //遍历集合
for(Object obj:objs) {
System.out.print(obj + " ");
}
System.out.println();
}
}
}
BeanHandler和BeanListHandler类的用法
- BeanHandler类功能:将第一条记录存放到一个JavaBean中
- BeanListHandler类功能:将所有记录存放到一个List集合包装的JavaBean中
JavaBean
public class Person {
private int p_id; //这里的成员变量必须和数据库中的成员变量一致
private String p_name;
private int p_age;
public Person() {
}
public Person(int p_id,String p_name,int p_age) {
this.p_id = p_id;
this.p_name = p_name;
this.p_age = p_age;
}
public int getP_id() {
return p_id;
}
public void setP_id(int p_id) {
this.p_id = p_id;
}
public String getP_name() {
return p_name;
}
public void setP_name(String p_name) {
this.p_name = p_name;
}
public int getP_age() {
return p_age;
}
public void setP_age(int p_age) {
this.p_age = p_age;
}
@Override
public String toString() {
return getP_id() + " " + getP_name() + " " + getP_age();
}
}
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
public class FirstApp {
static final String driver = "con.mysql.jdbc.Driver";
static final String url = "jdbc:mysql://localhost:3306/mydb";
static final String user = "root";
static final String passwd = "kyle";
public static void main(String[] args) throws SQLException {
Connection conn = null;
// Step 1: Register JDBC driver
DbUtils.loadDriver(driver);
// Step 2: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(url, user, passwd);
beanListHander(conn);
}
//将结果集的第一行数据,封装到JavaBean对象
//注意: 被封装成数据到JavaBean对象, 该JavaBean类必须有空参数构造
public static void beanHandler(Connection conn) throws SQLException {
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM person";
//调用方法,传递结果集实现类BeanHandler
// BeanHandler(Class<T> type)
Person s = qr.query(conn, sql, new BeanHandler<Person>(Person.class)); //Person类一个含有pid,pname,page变量的JavaBean
System.out.println(s); //输出:net.hackyle.DBUtils.Person@46238e3f
System.out.println(s.getP_id() + " " + s.getP_name() + " " + s.getP_age());
}
public static void beanListHander(Connection conn)throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM Person ";
//调用方法query,传递结果集处理实现类BeanListHandler
List<Person> list = qr.query(conn, sql, new BeanListHandler<Person>(Person.class));
for(Person s : list){
System.out.println(s);
}
}
}
ColumnListHandler类使用
功能:将结果集中的指定列的数据值,存放到一个List集合中。因为每个列的数据类型可能都是不同的,所以需要使用Object类型。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ColumnListHandler;
public class FirstApp {
static final String driver = "con.mysql.jdbc.Driver";
static final String url = "jdbc:mysql://localhost:3306/mydb";
static final String user = "root";
static final String passwd = "kyle";
public static void main(String[] args) throws SQLException {
Connection conn = null;
// Step 1: Register JDBC driver
DbUtils.loadDriver(driver);
// Step 2: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(url, user, passwd);
columnListHandler(conn);
}
public static void columnListHandler(Connection conn)throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM person;";
//调用方法 query,传递结果集实现类ColumnListHandler
//实现类构造方法中,使用字符串的列名
List<Object> list = qr.query(conn, sql, new ColumnListHandler<Object>("p_name")); //把数据库中pname所在列的所有数据放在一个List中
for(Object obj : list){
System.out.println(obj);
}
}
}
/*输出:
huawei
asus
tencent
apple
*/
ScalarHandler类使用
适用于:结果集中有且只有一个结果(仅有一行一列)时的情形。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ScalarHandler;
public class FirstApp {
static final String driver = "con.mysql.jdbc.Driver";
static final String url = "jdbc:mysql://localhost:3306/mydb";
static final String user = "root";
static final String passwd = "kyle";
public static void main(String[] args) throws SQLException {
Connection conn = null;
// Step 1: Register JDBC driver
DbUtils.loadDriver(driver);
// Step 2: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(url, user, passwd);
scalarHandler(conn);
}
public static void scalarHandler(Connection conn)throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT COUNT(*) FROM person";
//调用方法query,传递结果集处理实现类ScalarHandler
Object count = qr.query(conn, sql, new ScalarHandler<Long>()); //如果已经确定查询结果是个int型,则不用Object类型
System.out.println(count);
}
}
MapHandler和MapListHandler类的用法
功能概要:
- MapHandler类功能:将结果集的第一行数据封装到Map集合中,其中“键”是列名,“值”是这列的数据;
- MapListHandler类功能:将结果集的全部封装到Map集合中
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
public class FirstApp {
static final String driver = "con.mysql.jdbc.Driver";
static final String url = "jdbc:mysql://localhost:3306/mydb";
static final String user = "root";
static final String passwd = "kyle";
public static void main(String[] args) throws SQLException {
Connection conn = null;
// Step 1: Register JDBC driver
DbUtils.loadDriver(driver);
// Step 2: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(url, user, passwd);
mapHandler(conn);
mapListHandler(conn);
}
public static void mapHandler(Connection conn)throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM person";
//调用方法query,传递结果集实现类MapHandler
//返回值: Map集合,Map接口实现类, 泛型
Map<String,Object> map = qr.query(conn, sql, new MapHandler());
//遍历Map集合
for(String key : map.keySet()){
System.out.println(key+".."+map.get(key));
}
}
public static void mapListHandler(Connection conn)throws SQLException{
QueryRunner qr = new QueryRunner();
String sql = "SELECT * FROM person";
//调用方法query,传递结果集实现类MapListHandler
//返回值List集合, 存储的是Map集合
List<Map<String,Object>> list = qr.query(conn, sql, new MapListHandler());
//遍历集合list
for( Map<String,Object> map : list ){
for(String key : map.keySet()){
System.out.print(key+": "+map.get(key)+" ");
}
System.out.println();
}
}
}