十五、DAO 、BasicDao
1. apache-dbutils+ Druid(德鲁伊连接池)简化了JDBC开发,但还有不足2. 引出DAO、BasicDao3. 代码示例
utils类Student类BasicDAO类StudentDAOtest类 数据库总结
十五、DAO 、BasicDao 1. apache-dbutils+ Druid(德鲁伊连接池)简化了JDBC开发,但还有不足(1)SQL语句是固定,不能通过参数传入,通用性不好,需要进行改进,更方便执行增删改查
(2)对于select 操作,如果有返回值,返回类型不能固定,需要使用泛型
(3)将来的表很多,业务需求复杂,不可能只靠一个Java类完成
(1)DAO:data access object数据访问对象
(2)BasicDao:通用类,是专门和数据库交互的,即完成对数据库(表)的增删改查操作。
package demo.dao_.utils;
import com.alibaba.druid.pool.DruidDataSourceFactory;
import javax.sql.DataSource;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
public class JDBCUtilsByDruid {
//1. 建立德鲁伊连接池
private static DataSource dataSource;
//2. 加载德鲁伊配置文件
static {
Properties properties = new Properties();
try {
properties.load(new FileInputStream("src\druid.properties"));
dataSource = DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
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 throwables) {
throwables.printStackTrace();
}
}
}
Student类
package demo.dao_.domain;
import java.util.Date;
public class Student {
private int id;
private String name;
private Date birthday;
public Student() {
}
public Student(int id, String name, Date birthday) {
this.id = id;
this.name = name;
this.birthday = birthday;
}
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 Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "nStudent{" +
"id=" + id +
", name='" + name + ''' +
", birthday=" + birthday +
'}';
}
}
BasicDAO类
package demo.dao_.dao; import demo.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; public class BasicDAOStudentDAO{ private QueryRunner qu = new QueryRunner(); public int add_de_update(String sql,Object...parameters){ Connection connection = null; try { connection = JDBCUtilsByDruid.getConnection(); int update = qu.update(connection, sql, parameters); return update; } catch (SQLException throwables) { throw new RuntimeException(throwables); //将编译异常->运行异常抛出 } finally { JDBCUtilsByDruid.close(null,null,connection); } } public List Multiple_line(String sql,Class cla,Object...parameters){ Connection connection = null; try { connection = JDBCUtilsByDruid.getConnection(); List query = qu.query(connection, sql, new BeanListHandler<>(cla), parameters); return query; } catch (SQLException throwables) { throw new RuntimeException(throwables); //将编译异常->运行异常抛出 } finally { JDBCUtilsByDruid.close(null,null,connection); } } public T Single_line(String sql,Class cla,Object...parameters){ Connection connection = null; try { connection = JDBCUtilsByDruid.getConnection(); T t = qu.query(connection, sql, new BeanHandler<>(cla), parameters); return t; } catch (SQLException throwables) { throw new RuntimeException(throwables); //将编译异常->运行异常抛出 } finally { JDBCUtilsByDruid.close(null,null,connection); } } public Object Single_data(String sql,Object...parameters){ Connection connection = null; try { connection = JDBCUtilsByDruid.getConnection(); Object o = qu.query(connection, sql, new ScalarHandler(), parameters); return o; } catch (SQLException throwables) { throw new RuntimeException(throwables); //将编译异常->运行异常抛出 } finally { JDBCUtilsByDruid.close(null,null,connection); } } }
package demo.dao_.dao; import demo.dao_.domain.Student; public class StudentDAO extends BasicDAOtest类{ //1. 继承 BasicDAO 的通用方法 //2. 根据业务需求,可以编写特有的方法. }
package demo.dao_.test;
import demo.dao_.dao.StudentDAO;
import demo.dao_.domain.Student;
import org.junit.jupiter.api.Test;
import java.util.List;
public class Testdao {
@Test
public void test(){
StudentDAO studentDAO = new StudentDAO();
//1. 查询多条记录
String sql = "select * from student where id > ?";
List list = studentDAO.Multiple_line(sql, Student.class, 0);
for (Student student : list) {
System.out.println(student);
}
//2. 查询一条记录
String sql2 = "select * from student where id = ?";
Student student = studentDAO.Single_line(sql2, Student.class, 2);
System.out.println(student);
//3. 查询单个记录
String sql3 = "select birthday from student where id = ?";
Object object = studentDAO.Single_data(sql3, 1);
System.out.println(object);
//4.增加一条数据
String sql4 = "insert into student values(null,?,?)";
int i = studentDAO.add_de_update(sql4, "爱吃凉拌辣芒果", "2000-01-01");
System.out.println( i > 0 ? "执行成功" : "执行失败");
}
}
数据库总结
总结:
当高并发时,多个程序访问数据库请求直接与数据库连接,会造成访问数据库速度变慢,甚至出现数据库奔溃的情况,那么我们引入连接池作为缓冲,用它来控制与数据库的通断,此时用户程序只是从这个连接池获得连接或者释放连接,实际上与数据库连接的是连接池。举个例子就像大群人进机场,总是有个缓冲的地方。
常用的连接池有C3P0,Druid,DBCP等,其中C3PO数据库连接池,速度相对较慢,稳定性不错;Druid(德鲁伊) 是阿里提供的数据库连接池,集DBCP、C3PO、Proxool优点于一身的数据库连接池。我们选择使用Druid连接池,并且自己建立一个基于Druid的工具类,JDBCUtilsByDruid,用它的getConnection(),close(result,statement,connection)方法,分别获取连接和释放连接。并在druid.properties中配置好与数据库连接的用户名、密码、数据库名等信息。
连接的问题解决了,那么来到数据处理部分,在我们select查询数据时,必须在结果集result关闭之前操作,否则一旦结果集提前关闭了,select操作无效。此外,只有保持连接,才能进一步对查询的数据进行操作。此时我们想到,如果能把查询到数据存到一个集合中,这样即使断开连接,这些数据还可以进一步操作。所以我们使用Apache提供的一个开源JDBC工具类库,在它的DBUtils包下,使用QueryRunner类中的query方法,update方法,分别来进行查询和增删改的操作,注意查询的时候分为某行某列的单数据查询用ScalarHandler,多数据查询用BeanListHandler类。与此同时,我们需要将要操作的表,建立一个对应的java类,这个类根据表的属性设置对应的私有属性,以及构造函数,toString方法,getter和setter方法。这个类我们称作javabean/domain/pojo。
利用Druid+Apache-DBUtils,连接和数据处理的问题解决了,但是有个新的问题,就是sql语句过硬,无法写入参数,已经固定写死。如果一个数据库操作的表过多,对于select 操作,如果有返回值,返回类型(domain)不能固定,需要使用泛型。
所以我们把之前的过程模块化,把其中的:连接部分,sql增、删、改、查通用部分,断开连接部分。写成BasicDao类且为泛型,因为这是公共的部分。对于每一个表,分别建立对应的类,我们称为domain。接着,我们分别对每个表的操作,写成一个独有的DAO类,并且继承BasicDao类。
分别建立四个包包:domain,dao,utils,test来存放domain的类,dao的类,JDBCUtilsByDruid工具类,测试类。



