DAO模式

DAO模式

掌握DAO模式

​ DAO (DataAccessobjects 数据存取对象)是指位于业务逻辑和持久化数据之间实现对持久化数据的访问。通俗来讲,就是将数据库操作都封装起来。

对外提供相应的接口

在面向对象设计过程中,有一些"套路”用于解决特定问题称为模式。

DAO 模式提供了访问关系型数据库系统所需操作的接口,将数据访问和业务逻辑分离对上层提供面向对象的数据访问接口。

从以上 DAO 模式使用可以看出,DAO 模式的优势就在于它实现了两次隔离。

  • 隔离了数据访问代码和业务逻辑代码。业务逻辑代码直接调用DAO方法即可,完全感觉不到数据库表的存在。分工明确,数据访问层代码变化不影响业务逻辑代码,这符合单一职能原则,降低了藕合性,提高了可复用性。
  • 隔离了不同数据库实现。采用面向接口编程,如果底层数据库变化,如由 MySQL 变成 Oracle 只要增加 DAO 接口的新实现类即可,原有 MySQ 实现不用修改。这符合 "开-闭" 原则。该原则降低了代码的藕合性,提高了代码扩展性和系统的可移植性。

一个典型的DAO 模式主要由以下几部分组成。

  • 1、DAO接口: 把对数据库的所有操作定义成抽象方法,可以提供多种实现。
  • 2、DAO 实现类: 针对不同数据库给出DAO接口定义方法的具体实现。
  • 3、实体类:用于存放与传输对象数据。
  • 4、数据库连接和关闭工具类: 避免了数据库连接和关闭代码的重复使用,方便修改。

实例:

测试类:

//测试类
public class Test {
    public static void main(String[] args) {
        Emp e = new Emp(9950,"HELLO","CLERK",5050.0F,300,null,new Date(),20);
        EmpDao dao = new EmpDaoImpl();
        //添加
//        int count = dao.saveEmp(e);
//        System.out.println(count);
        //查找
//        Emp e2 = dao.selectEmp(7369);
//        System.out.println(e2.toString());
        //删除
//        int count = dao.deleteEmp(9950);
//        System.out.println(count);
        //替换
//        int count = dao.updateEmp(e,4545);
//        System.out.println(count);
//        查询所有员工
//        List<Emp> e3 = dao.selectAllEmp();
//        for (Emp e4: e3) {
//            System.out.println(e4.toString());
//        }
        //根据入职时间查找员工
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//        Date d1 =null;
//        Date d2 =null;
//
//        try {
//            d1 = sdf.parse("1980-01-01");
//            d2 = sdf.parse("1990-01-01");
//        } catch (ParseException ex) {
//            ex.printStackTrace();
//        }
//        List<Emp>e7 = dao.TimeEmp(d1,d2);
//        for (Emp e8: e7) {
//            System.out.println(e8.toString());
//        }

        //模糊查询
//        List<Emp> e5 = dao.vagueSelectEmp("%A%");
//        for (Emp e6: e5) {
//            System.out.println(e6.toString());
//        }
    }
}

实体类:

package mysqltest.pojo;

import java.util.Date;

public class Emp {
    private Integer empno;
    private String ename;
    private String job;
    private Float Sal;
    private Integer comm;
    private Integer mgr;
    private Date hiredate;
    private int deptno;

    public Integer getEmpno() {
        return empno;
    }

    public void setEmpno(Integer empno) {
        this.empno = empno;
    }

    public String getEname() {
        return ename;
    }

    public void setEname(String ename) {
        this.ename = ename;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public Float getSal() {
        return Sal;
    }

    public void setSal(Float sal) {
        Sal = sal;
    }

    public Integer getComm() {
        return comm;
    }

    public void setComm(Integer comm) {
        this.comm = comm;
    }

    public Integer getMgr() {
        return mgr;
    }

    public void setMgr(Integer mgr) {
        this.mgr = mgr;
    }

    public Date getHiredate() {
        return hiredate;
    }

    public void setHiredate(Date hiredate) {
        this.hiredate = hiredate;
    }

    public int getDeptno() {
        return deptno;
    }

    public void setDeptno(int deptno) {
        this.deptno = deptno;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empno=" + empno +
                ", ename='" + ename + '\'' +
                ", job='" + job + '\'' +
                ", Sal=" + Sal +
                ", comm=" + comm +
                ", mgr=" + mgr +
                ", hiredate=" + hiredate +
                ", deptno=" + deptno +
                '}';
    }

    public Emp(Integer empno, String ename, String job, Float sal, Integer comm, Integer mgr, Date hiredate, int deptno) {
        this.empno = empno;
        this.ename = ename;
        this.job = job;
        Sal = sal;
        this.comm = comm;
        this.mgr = mgr;
        this.hiredate = hiredate;
        this.deptno = deptno;
    }

    public Emp() {
    }

}

DAO接口:

package mysqltest.dao;

import mysqltest.pojo.Emp;

import java.util.Date;
import java.util.List;

public interface EmpDao {
    //添加
    public int saveEmp(Emp e);
    //删除
    public int deleteEmp(int empno);
    //更新
    public int updateEmp(Emp e,int empno);
    //查找
    public Emp selectEmp(int empno);
    //返回所有值
    public List<Emp> selectAllEmp();
    //模糊查找
    public List<Emp> vagueSelectEmp(String str);
    //根据入职时间区间查找
    public List<Emp> TimeEmp(Date d1,Date d2);
}

数据库连接和关闭工具类和额外的功能块(有部分冗余):

package mysqltest.dao.impl;

import mysqltest.pojo.Emp;

import java.io.IOException;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class BaseDao {
    private static String driver;
    private static String url;
    private static String user;
    private static String password;


    //注册驱动
    static {
        Properties p = new Properties();
        try {
            p.load(BaseDao.class.getClassLoader().getResourceAsStream("mysqltest/jdbc.properties"));
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("配置文件加载异常");
        }
        driver = p.getProperty("DRIVER");
        url = p.getProperty("URL");
        user = p.getProperty("USER");
        password = p.getProperty("PASSWORD");

        try {
            Class.forName(driver);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException("注册驱动异常");
        }
    }
    //连接数据库
    public static Connection getConnection(){
        try {
            return DriverManager.getConnection(url, user, password);
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("连接数据库异常");
        }
    }
    //关闭数据库连接
    public static void closeAll(Connection conn, Statement stmt, ResultSet rs){
        if(rs!=null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
                throw new RuntimeException("ResultSet关闭异常");
            }
        }
        if(stmt!=null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
                throw new RuntimeException("Statement关闭异常");
            }
        }
        if(conn!=null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
                throw new RuntimeException("Connection关闭异常");
            }
        }
    }
    //executeUpdate执行SQL并返回一个int值(受影响的行数)
    public int executeUpdate(String sql,Object... programs){
        Connection con = null;
        PreparedStatement preparedStatement= null;
        Integer count;
        try{
            //初始化
            con=getConnection();
            preparedStatement = con.prepareStatement(sql);
           //给preparedStatement设置参数
            for(int i = 0;i < programs.length;i++){
                preparedStatement.setObject(i+1,programs[i]);
            }
            //返回count
            count = preparedStatement.executeUpdate();
            return count;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            throw new RuntimeException("statement异常");
        } finally {
            closeAll(con,preparedStatement,null);
        }
    }
    //executeQuery执行SQL并返回一个Emp对象
    public Emp executeQuery(String sql, int deptno){
        Connection con = null;
        PreparedStatement preparedStatement= null;
        ResultSet resultSet = null;
        Emp emp = new Emp();
        try{
            //初始化
            con = getConnection();
            preparedStatement = con.prepareStatement(sql);
            //给preparedStatement设置参数
            preparedStatement.setInt(1,deptno);
            resultSet = preparedStatement.executeQuery();
            //遍历结果集赋值
            if (resultSet.next()){
                emp.setEmpno(resultSet.getInt(1));
                emp.setEname(resultSet.getString(2));
                emp.setJob(resultSet.getString(3));
                emp.setSal(resultSet.getFloat(4));
                emp.setComm(resultSet.getInt(5));
                emp.setMgr(resultSet.getInt(6));
                emp.setHiredate(resultSet.getDate(7));
                emp.setDeptno(resultSet.getInt(8));
            }
            return emp;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            throw new RuntimeException("statement异常");
        } finally {
            closeAll(con,preparedStatement,null);
        }
    }

    //executeQuery执行SQL并返回一个Emp的List集合
    public List<Emp> executeQuery(String sql){
        Connection con = null;
        PreparedStatement preparedStatement= null;
        ResultSet resultSet = null;
        List<Emp> e = new ArrayList<>();
        try{
            //初始化
            con = getConnection();
            preparedStatement = con.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            //遍历结果集赋值
            while(resultSet.next()){
                Emp emp = new Emp();
                emp.setEmpno(resultSet.getInt(1));
                emp.setEname(resultSet.getString(2));
                emp.setJob(resultSet.getString(3));
                emp.setSal(resultSet.getFloat(4));
                emp.setComm(resultSet.getInt(5));
                emp.setMgr(resultSet.getInt(6));
                emp.setHiredate(resultSet.getDate(7));
                emp.setDeptno(resultSet.getInt(8));
                e.add(emp);
            }
            return e;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            throw new RuntimeException("statement异常");
        } finally {
            closeAll(con,preparedStatement,null);
        }
    }
    //模糊查询 返回List<Emp>集合
    public List<Emp> executeQuery(String sql,Object...programs){
        Connection con = null;
        PreparedStatement preparedStatement= null;
        ResultSet resultSet = null;
        List<Emp> e = new ArrayList<>();
        try{
            //初始化
            con = getConnection();
            preparedStatement = con.prepareStatement(sql);
            //给preparedStatement设置参数
            for (int i = 0; i < programs.length; i++) {
                preparedStatement.setObject(i+1, programs[i]);
            }
            resultSet = preparedStatement.executeQuery();
            //遍历结果集赋值
            while(resultSet.next()){
                Emp emp = new Emp();
                emp.setEmpno(resultSet.getInt(1));
                emp.setEname(resultSet.getString(2));
                emp.setJob(resultSet.getString(3));
                emp.setSal(resultSet.getFloat(4));
                emp.setComm(resultSet.getInt(5));
                emp.setMgr(resultSet.getInt(6));
                emp.setHiredate(resultSet.getDate(7));
                emp.setDeptno(resultSet.getInt(8));
                e.add(emp);
            }
            return e;
        } catch (SQLException throwables) {
            throwables.printStackTrace();
            throw new RuntimeException("statement异常");
        } finally {
            closeAll(con,preparedStatement,null);
        }
    }
}

实现类

package mysqltest.dao.impl;

import mysqltest.dao.EmpDao;
import mysqltest.pojo.Emp;

import java.util.Date;
import java.util.List;

public class EmpDaoImpl extends BaseDao implements EmpDao {
    @Override
    public int saveEmp(Emp e) {
        String sql ="INSERT INTO emp VALUES (?,?,?,?,?,?,?,?)";
        return super.executeUpdate(sql,e.getEmpno(),e.getEname(),e.getJob(),e.getSal(),e.getComm(),e.getMgr(),e.getHiredate(),e.getDeptno());
    }

    @Override
    public int deleteEmp(int empno) {
        String sql ="DELETE FROM emp WHERE empno = ?";
        return super.executeUpdate(sql,empno);
    }

    @Override
    public int updateEmp(Emp e,int empno) {
        String sql = "UPDATE emp SET empno = ?,ename = ?,job = ?,Sal = ?,comm=?,mgr=?,hiredate=?,deptno=? WHERE empno = ?";
        return super.executeUpdate(sql,e.getEmpno(),e.getEname(),e.getJob(),e.getSal(),e.getComm(),e.getMgr(),e.getHiredate(),e.getDeptno(),empno);
    }

    @Override
    public Emp selectEmp(int empno) {
        String sql = "SELECT * FROM emp WHERE empno = ?";
        return super.executeQuery(sql,empno);
    }

    @Override
    public List<Emp> selectAllEmp() {
        String sql = "SELECT * FROM emp ";
        return super.executeQuery(sql);
    }

    @Override
    public List<Emp> vagueSelectEmp(String str) {
        String sql = "SELECT * FROM emp WHERE ename like ?";
        return super.executeQuery(sql,str);
    }

    @Override
    public List<Emp> TimeEmp(Date d1, Date d2) {
        String sql ="SELECT * FROM emp WHERE hiredate BETWEEN ? AND ?";
        return super.executeQuery(sql,d1,d2);
    }
}

Properties配置

​ 开发中获得连接的四个参数(驱动,URL,用户名,密码)通常都存在配置文件中,方便后期维护,程序如果需要更换数据库,只需要修改配置文件即可。

通常情况下,我们习惯使用properties文件,此文件要求:

  • 文件位置:任意,建议src下(非web应用)、classpath(web应用)

  • 文件名:任意,扩展名为properties

  • 文件内容:一行一组数据,格式“key=value”(不要有空格)

    • key名自定义,如果是多个单词,习惯使用点分隔,例如:jdbc.driver

    • Value值不支持中文,如果需要使用非英文字符,讲进行Unicode转换。

1.创建配置文件

driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/student
user=root
password=root

2.加载配置文件:ResourceBundle对象


public class TextBundle {
 
	public static String driver;
	public static String url;
	public static String user;
	public static String password;
	
	static {
		ResourceBundle bundle = ResourceBundle.getBundle("db");
		driver = bundle.getString("driver");
		url = bundle.getString("url");
		user = bundle.getString("user");
		password = bundle.getString("password");
	}
}

3.加载配置文件:Properties对象


public class TextBundle {
 
	public static String driver;
	public static String url;
	public static String user;
	public static String password;
	
	static {
		//1、通过当前类获取类加载器
		ClassLoader classloader = TextBundle.class.getClassLoader();
		//2、通过类加载器的方法获得一个输入流
		InputStream is = classloader.getResourceAsStream("db.properties");
		//3、创建一个properties对象
		Properties props = new Properties();
		//4、加载输入流
		try {
			props.load(is);//可以把步骤2和这个写在一起
		} catch (IOException e) {
			e.printStackTrace();
		}
		//5、获得参数值
		driver = props.getProperty("driver");
		url = props.getProperty("url");
		user = props.getProperty("user");
		password = props.getProperty("password");
	}
}
posted @ 2021-10-27 21:30  beamsoflight  阅读(421)  评论(0编辑  收藏  举报