一. 储备知识
DBUtils提供通用的对数据库表操作的增删改查的方法,有如下方法:
- 增删改
- 查询一条记录封装为一个对象
- 查询多条记录封装为对象的集合
- 查询表中数据的总记录条数
- 批处理的方法(批量增删改)
注意 : 要导入dbutils的jar包才能实现本次介绍的方法封装。
使用DBUtils第三方工具完成方法的封装
类 | 作用 |
---|---|
QueryRunner | 封装了增删改查的方法 |
ResultSetHandler | 结果集的帮助处理类 |
BeanHandler | 用来将一条记录封装为一个对象的工具类 |
BeanListHandler | 用来将多条记录封装为对象的集合 |
ScalarHandler | 可以将查询到的第一行第一列的数据返回 |
二. 例子
注意:
- 本次例子采用c3p0数据库连接池获取数据库连接,如果忘记,可以详看Day3_JDBC——C3P0数据库连接池的创建,或者采用DBCP数据库连接池请详看Day3_JDBC——DBCP数据库连接池的创建
- 以后都是一个表对应一个Dao,比如users表,对应一个UserDao(UserDao继承BaseDao),UserDao里面有关于users表的具体操作方法(比如根据用户名密码查询数据库是否与里面的数据一致,一致才可以登录成功,否则登录失败。。。等等)。
项目的目录结构如下图:
c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
<!-- named-config的name属性值就是当前配置的一套配置名
在创建连接池时可以根据配置名加载此套配置信息
-->
<named-config name="webDataSource">
<property name="jdbcUrl">jdbc:mysql://localhost:3306/myemployees?
rewriteBatchedStatements=true
</property>
<property name="driverClass">com.mysql.jdbc.Driver</property>
<property name="user">root</property>
<property name="password">123456</property>
<!-- 最小连接数 -->
<property name="minPoolSize">5</property>
<!-- 最大连接数 -->
<property name="maxPoolSize">30</property>
<!-- 初始化的连接数 -->
<property name="initialPoolSize">10</property>
<!-- 需要时一次性创建的连接数 -->
<property name="acquireIncrement">5</property>
<!-- 缓存多少个Statement对象 -->
<property name="maxStatements">15</property>
</named-config>
</c3p0-config>
JDBCUtils.java
package com.atguigu.utils;
import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
import com.mchange.v2.c3p0.ComboPooledDataSource;
public class JDBCUtils {
private static DataSource source = new ComboPooledDataSource("webDataSource");
public static Connection getConn() {
Connection conn = null;
try {
conn = source.getConnection();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return conn;
}
public static void closeConn(Connection conn) {
if(conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
BaseDao.java
package com.atguigu.dao;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import com.atguigu.utils.JDBCUtils;
public class BaseDao {
private QueryRunner runner = new QueryRunner();
//增删改
public int update(String sql, Object...params) {
Connection conn = JDBCUtils.getConn();
int count = 0;
try {
count = runner.update(conn, sql, params);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
JDBCUtils.closeConn(conn);
}
return count;
}
//查询一条记录封装为对象的方法
public <T>T getBean(Class<T> type, String sql, Object...params){
Connection conn = JDBCUtils.getConn();
T t = null;
try {
//BeanHandler将查询到的记录封装为一个对象
//type类中必须由无参构造器,type类的属性名必须和sql查询的列名一致
t = runner.query(conn, sql, new BeanHandler<>(type), params);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println("t为:" + t);
}finally {
JDBCUtils.closeConn(conn);
}
return t;
}
//查询多条记录并封装为对象的集合
public <T>List<T> getBeanList(Class<T> type, String sql, Object...params){
Connection conn = JDBCUtils.getConn();
List<T> list = null;
try {
list = runner.query(conn, sql, new BeanListHandler<>(type), params);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
JDBCUtils.closeConn(conn);
}
return list;
}
//查询数据库表的总记录条数,可变参数列表是0个~n个参数,
//如果没有参数,则不需要传入可变参数列表,连null也不用传
public long getCount(String sql, Object...params) {
Connection conn = JDBCUtils.getConn();
//ScalarHandler:无参构造器默认将查询到的第一行第一列数据封装为对象返回
// 如果是整数类型返回真实类型Long
// 如果真实返回类型是String,并提升为Object返回
long count = 0;
try {
count = (long) runner.query(conn, sql, new ScalarHandler(), params);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
JDBCUtils.closeConn(conn);
}
return count;
}
//批量增删改,它需要知道执行多少次,每次的参数是什么
//所以方法中的二维数据参数,第一维代表批处理执行的次数
//第二维代表每次批处理需要的参数列表
public void batchUpdate(String sql, Object[][] params) {
Connection conn = JDBCUtils.getConn();
try {
runner.batch(conn, sql, params);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
JDBCUtils.closeConn(conn);
}
}
}
TestBaseDao.java
package com.atguigu.test;
import java.util.List;
import org.junit.jupiter.api.Test;
import com.atguigu.bean.User;
import com.atguigu.dao.BaseDao;
class TestBaseDao {
BaseDao dao = new BaseDao();
//测试增加记录的操作
@Test
public void test1() {
String sql = "insert into users (username, password, balance) "
+ "values (?, ?, ?)";
String username = "liwu";
String password = "123";
double balance = 1000;
int count = dao.update(sql, username, password, balance);
System.out.println(count);
}
//测试删除记录的操作
@Test
public void test2() {
String sql = "delete from users where username = ?";
String username = "liwu";
int count = dao.update(sql, username);
System.out.println(count);
}
//测试修改记录的操作
@Test
public void test3() {
String sql = "update users set username = ? where username = ?";
String username1 = "lisi";
String username2 = "liliu";
int count = dao.update(sql, username1, username2);
System.out.println(count);
}
//测试查询一条记录并封装为对象
@Test
public void test4() {
String sql = "select id, username, password, balance "
+ "from users where id = ?";
int id = 1;
User user = dao.getBean(User.class, sql, id);
System.out.println(user);
}
//测试查询多条记录并封装为对象的集合
@Test
public void test5() {
String sql = "select id, username, password, balance "
+ "from users where id > ?";
int id = 0;
List<User> list = dao.getBeanList(User.class, sql, id);
System.out.println(list);
}
//测试查询数据库表的总记录条数
@Test
public void test6() {
String sql = "select count(*) from users";
long count = dao.getCount(sql);
System.out.println(count);
}
}