为什么要有 BasicDAO
apache-dbutils + Druid 简化了 JDBC 开发,但还有不足:
- SQL语句是固定,不能通过参数传入,通用性不好,需要进行改进,更方便执行增删改查
- 对于 select 操作,如果有返回值,返回类型不能固定,需要使用泛型
- 将来的表很多,业务需求复杂,不可能只靠一个 Java 类完成
- BasicDAO 示意图
基本说明
DAO:Data Access Object 数据访问对象
- 这样的通用类,称为
BasicDao
,是专门和数据库交互的,即完成对数据库(表)的crud
操作 - 在
BaiscDao
的基础上,实现一张表对应一个Dao
,更好的完成功能,比如Customer表 --- Customer.java类(javabean) --- CustomerDao.java
BasicDAO 应用实例
完成一个简单设计 dao_
dao_.utils
:// 工具类dao_.domain
:// javabeandao_.dao
:// 存放XxxDAO
和BasicDAO
dao_.test
:// 写测试类
目录结构
ActorDAO 类
package dao_.dao;
/**
* @Author: Gin
* @Description:
* @Modified By: Gin
* @Date: Created in 19:24 2021/9/15
*/
public class ActorDAO extends BasicDAO{
// 1. ActorDAO 类中含有 BasicDAO 类中的所有方法
// 2. 可以根据业务逻辑添加新的方法
}
BasicDAO 类
package dao_.dao;
import dao_.utils.JDBCUtilsByDruid;
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 java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
/**
* @Author: Gin
* @Description: BasicDAO:其他 DAO 类的父类
* @Modified By: Gin
* @Date: Created in 18:54 2021/9/15
*/
public class BasicDAO<T> {
private QueryRunner queryRunner = new QueryRunner();
// 开发通用的 DML 方法,针对任意的表
public int update(String sql, Object... parameters){
Connection connection = null;
try{
connection = JDBCUtilsByDruid.getConnection();
int rows = queryRunner.update(connection, sql, parameters);
return rows;
} catch (SQLException e) {
// 将编译异常转为运行异常抛出
throw new RuntimeException(e);
} finally {
JDBCUtilsByDruid.close(null, null, connection);
}
}
// 返回多个对象(即查询的结果是多行的),针对任意表
/**
* @param sql:SQL语句,可以有 ?
* @param tClass:传入一个类的 Class 对象,比如 Actor.class
* @param parameters:传入 ? 的具体值,可以有多个
* @return 根据 Actor.class 返回对应的 ArrayList 集合
*/
public List<T> queryMultiple(String sql, Class<T> tClass, Object... parameters){
Connection connection = null;
try{
connection = JDBCUtilsByDruid.getConnection();
List<T> query = queryRunner.query(connection, sql, new BeanListHandler<>(tClass), parameters);
return query;
} catch (SQLException e) {
// 将编译异常转为运行异常
throw new RuntimeException(e);
} finally {
JDBCUtilsByDruid.close(null, null, connection);
}
}
// 查询单行结果
public T querySingle(String sql, Class<T> tClass, Object... parameters){
Connection connection = null;
try{
connection = JDBCUtilsByDruid.getConnection();
T query = queryRunner.query(connection, sql, new BeanHandler<>(tClass), parameters);
return query;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtilsByDruid.close(null, null, connection);
}
}
// 查询单行单列的方法,即返回的是单个值的方法
public Object queryScalar(String sql, Object... parameters){
Connection connection = null;
try{
connection = JDBCUtilsByDruid.getConnection();
Object query = queryRunner.query(connection, sql, new ScalarHandler(), parameters);
return query;
} catch (SQLException e) {
throw new RuntimeException(e);
} finally {
JDBCUtilsByDruid.close(null, null, connection);
}
}
}
Actor 类
package dao_.domain;
import java.util.Date;
/**
* @Author: Gin
* @Description:
* @Modified By: Gin
* @Date: Created in 18:52 2021/9/15
*/
public class Actor {
private Integer id;
private String name;
private String sex;
private Date borndate;
private String phone;
// 无参构造器
// 全参数构造器
// get/set 方法
// toString 方法
// HashCode&equals
TestDAO 类
package dao_.test;
import dao_.dao.ActorDAO;
import dao_.domain.Actor;
import org.junit.Test;
import java.util.List;
/**
* @Author: Gin
* @Description:
* @Modified By: Gin
* @Date: Created in 19:25 2021/9/15
*/
public class TestDAO {
@Test
public void testActorDAO(){
// 获取 actorDAO 对象
ActorDAO actorDAO = new ActorDAO();
// 1. 查询多条语句
List<Actor> list = actorDAO.queryMultiple("select * from actor where id >= ?", Actor.class, 1);
System.out.println("===查询多条语句结果如下===");
for (Actor actor : list) {
System.out.println(actor);
}
// 2. 查询单行语句
Actor actor = (Actor) actorDAO.querySingle("select * from actor where id = ?", Actor.class, 3);
System.out.println("===查询单行语句的结果如下===");
System.out.println(actor);
// 3. 查询单行单列
Object o = actorDAO.querySingle("select name from actor where id = ?", Actor.class, 2);
System.out.println("===查询单行单列的结果如下===");
System.out.println(o);
// 4. DML 操作
int rows = actorDAO.update("insert into actor values(null, ?, ?, ?, ?)",
"Vermouth", "女", "1968-12-24", "4869");
System.out.println(rows > 0 ? "修改成功" : "修改无效");
}
}
JDBCUtilsByDruid
package dao_.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
* @Author: Gin
* @Description:
* @Modified By: Gin
* @Date: Created in 17:00 2021/9/15
*/
public class JDBCUtilsByDruid {
private static DataSource dataSource;
// 在静态块中完成对 DataSource 的初始化
static {
Properties properties = new Properties();
try{
properties.load(new FileInputStream("src\\druid.properties"));
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
// 获取 Connection 连接
public static Connection getConnection() throws SQLException {
return dataSource.getConnection();
}
// 放回连接
public static void close(ResultSet resultSet, Statement statement, Connection connection){
// 判断是否为空
try{
if(resultSet != null){
resultSet.close();
}
if(statement != null){
statement.close();
}
if(connection != null){
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}