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");
	}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM