Java初学笔记45-【DAO 、BasicDao、数据库总结】

十五、DAO 、BasicDao

1. apache-dbutils+ Druid(德鲁伊连接池)简化了JDBC开发,但还有不足

(1)SQL语句是固定,不能通过参数传入,通用性不好,需要进行改进,更方便执行增删改查
(2)对于select 操作,如果有返回值,返回类型不能固定,需要使用泛型
(3)将来的表很多,业务需求复杂,不可能只靠一个Java类完成

2. 引出DAO、BasicDao

(1)DAO:data access object数据访问对象
(2)BasicDao:通用类,是专门和数据库交互的,即完成对数据库(表)的增删改查操作。
在这里插入图片描述

3. 代码示例

在这里插入图片描述

utils类

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;

/**
 * @Package: demo.datasource
 * @ClassName: JDBCUtilsByDruid
 * @Author: 爱吃凉拌辣芒果
 * @CreateTime: 2022/3/9 16:27
 * @Description: 基于Druid(德鲁伊)的 JDBCUtils 工具类
 */
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();
        }
    }

    /**
     * 方法1:获取德鲁伊连接池的“连接”
     * @return
     * @throws SQLException
     */
    public static Connection getConnection() throws SQLException {
        return dataSource.getConnection();
    }

    /**方法2:断开与德鲁伊连接池的"连接"
     *
     * @param resultSet
     * @param statement
     * @param connection
     */
    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;

/**
 * @Package: demo.dao_.domain
 * @ClassName: Student
 * @Author: 爱吃凉拌辣芒果
 * @CreateTime: 2022/3/10 19:07
 * @Description:
 */
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;

/**
 * @Package: demo.dao_.dao
 * @ClassName: BasicDAO
 * @Author: 爱吃凉拌辣芒果
 * @CreateTime: 2022/3/10 19:34
 * @Description:
 */
public class BasicDAO<T> {
    private QueryRunner qu = new QueryRunner();

    /**
     * 实现对任何表的增加、删除、修改操作
     * @param sql  sql语句
     * @param parameters  传入sql语句的参数
     * @return  影响的行数
     */
    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);
        }
    }


    /**
     * 返回多个对象(即查询的结果是多行), 针对任意表
     * @param sql
     * @param cla
     * @param parameters
     * @return
     */
    public List<T> Multiple_line(String sql,Class<T> cla,Object...parameters){
        Connection connection = null;
        try {
            connection = JDBCUtilsByDruid.getConnection();
            List<T> query = qu.query(connection, sql, new BeanListHandler<>(cla), parameters);
            return query;
        } catch (SQLException throwables) {
            throw new RuntimeException(throwables); //将编译异常->运行异常抛出
        } finally {
            JDBCUtilsByDruid.close(null,null,connection);
        }
    }

    /**
     * 返回单个对象(即查询的结果是一行), 针对任意表
     * @param sql
     * @param cla
     * @param parameters
     * @return
     */
    public T Single_line(String sql,Class<T> 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);
        }
    }

    /**
     * 返回单个数据(即查询的结果是某一行某一列), 针对任意表
     * @param sql
     * @param parameters
     * @return
     */
    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);
        }
    }
}

StudentDAO

package demo.dao_.dao;

import demo.dao_.domain.Student;

/**
 * @Package: demo.dao_.dao
 * @ClassName: StudentDAO
 * @Author: 爱吃凉拌辣芒果
 * @CreateTime: 2022/3/10 20:14
 * @Description:  Student独有的操作类
 */
public class StudentDAO extends BasicDAO<Student>{
    //1. 继承 BasicDAO 的通用方法
    //2. 根据业务需求,可以编写特有的方法.
}

test类

package demo.dao_.test;

import demo.dao_.dao.StudentDAO;
import demo.dao_.domain.Student;
import org.junit.jupiter.api.Test;

import java.util.List;

/**
 * @Package: demo.dao_.test
 * @ClassName: Testdao
 * @Author: 爱吃凉拌辣芒果
 * @CreateTime: 2022/3/10 20:15
 * @Description:   测试 StudentDAO 对 Student表的操作
 */
public class Testdao {

    @Test
    public void test(){
        StudentDAO studentDAO = new StudentDAO();

        //1. 查询多条记录
        String sql = "select * from student where id > ?";
        List<Student> 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工具类,测试类。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱吃凉拌辣芒果

不断学习,不断进步,共勉~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值