1. 程式人生 > >Java DAO模式 關係配置

Java DAO模式 關係配置

本部落格根據《李興華--java8程式設計開發入門》視訊整理而來。

處理關係(瞭解)

現在已經實現了僱員和部門的基礎操作,但是在僱員裡面存在有mgr(所在部門負責人)和deptno(所在部門編號)兩個關聯欄位。

1. 修改VO類的定義:

    (1)修改Emp.java類

	private Emp mgr ;//部門負責人(仍是僱員)
	private Dept dept ;//所在部門資訊
	public void setMgr(Emp mgr) {
		this.mgr = mgr;
	}
	public void setDept(Dept dept) {
		this.dept = dept;
	}
	public Emp getMgr() {
		return mgr;
	}public Dept getDept() {
		return dept;
	}

表示僱員和領導關係以及僱員和部門關係。

    (2)修改部門定義(Dept.java)

	private List<Emp> emps; //部門中的員工們
	public void setEmps(List<Emp> emps) {
		this.emps = emps;
	}
	public List<Emp> getEmps() {
		return emps;
	}

2. 修改EmpDAOImpl子類:

    (1)增加資料時需要考慮到僱員的領導以及部門編號

	@Override
	public boolean doCreate(Emp vo) throws Exception {
		String sql = "insert into emp(empno,ename,job,hiredate,sal,comm,mgr,deptno) values (?,?,?,?,?,?,?,?)";
		this.pstmt = this.conn.prepareStatement(sql); // PreparedStatement 作為執行sql語句的物件,其中後面括號中的(sql)是要執行的sql語句;
		this.pstmt.setInt(1, vo.getEmpno());
		this.pstmt.setString(2, vo.getEname());
		this.pstmt.setString(3, vo.getJob());
		this.pstmt.setDate(4, new java.sql.Date(vo.getHiredate().getTime()));
		this.pstmt.setDouble(5, vo.getSal());
		this.pstmt.setDouble(6, vo.getComm());
		
		if(vo.getMgr() == null) { //沒有設定領導資料
			this.pstmt.setNull(7, Types.NULL);
		}else {
			this.pstmt.setInt(7, vo.getMgr().getEmpno()); //部門經理編號
		}
		if(vo.getDept() == null) { //沒有設定部門資料
			this.pstmt.setNull(8, Types.NULL);
		}else { //所在部門編號
			this.pstmt.setInt(8, vo.getDept().getDeptno());
		}
		
		return this.pstmt.executeUpdate() > 0;
	}

    (2)修改資料時也需要發生變化

	@Override
	public boolean doUpdate(Emp vo) throws Exception {
		String sql = "update emp set ename=?,job=?,hiredate=?,sal=?,comm=?,mgr=?,deptno=? where empno=?";
		this.pstmt = this.conn.prepareStatement(sql);
		this.pstmt.setString(1, vo.getEname());
		this.pstmt.setString(2, vo.getJob());
		this.pstmt.setDate(3, new java.sql.Date(vo.getHiredate().getTime()));
		this.pstmt.setDouble(4, vo.getSal());
		this.pstmt.setDouble(5, vo.getComm());
		
		if(vo.getMgr() == null) { //沒有設定領導資料
			this.pstmt.setNull(6, Types.NULL);
		}else {
			this.pstmt.setInt(6, vo.getMgr().getEmpno()); //部門經理編號
		}
		if(vo.getDept() == null) { //沒有設定部門資料
			this.pstmt.setNull(7, Types.NULL);
		}else { //所在部門編號
			this.pstmt.setInt(7, vo.getDept().getDeptno());
		}
		this.pstmt.setInt(8, vo.getEmpno());
		
		return this.pstmt.executeUpdate() > 0;
	}

    (3)在查詢單個僱員資訊的時候也需要進行全部內容的查詢。

也就是說現在的查詢裡面需要定義新的功能,目的是為了與之前的單表查詢分開。(單表->多表)

在IDAO裡面所寫的大部分方法都是支援單表操作的。而多表操作是Emp才具有的功能,於是需要在IEmpDAO中進行功能擴充。

擴充IEmpDAO方法

package com.fs.dao;
import java.util.List;
import com.fs.vo.Emp;
/**
 * 實現emp表的資料層的操作標準
 * @author 婉阿婉
 */
public interface IEmpDAO extends IDAO<Integer, Emp> {
	/**
	 * 查詢僱員的詳細資訊,包括僱員對應的領導資訊以及所在的部門資訊
	 * @param id 要查詢的僱員編號
	 * @return 所有的資料以VO物件返回,如果沒有則返回空
	 * @throws Exception SQL執行異常
	 */
	public Emp findByIdDetails(Integer id) throws Exception;

	/**
	 * 查詢僱員的完整資訊(部門經理人(僱員)所領導的僱員的資訊)
	 * @return 所有的資料物件以List集合返回,如果沒有資料則集合長度為0(size() == 0)
	 * @throws Exception SQL執行異常
	 */
	public List<Emp> findAllDetails() throws Exception;

	/**
	 * 分頁查詢僱員的完整資訊
	 * @param currentPage 當前所在的頁
	 * @param lineSize 每頁顯示的資料行數
	 * @param column 要進行模糊查詢的資料列
	 * @param keyword 模糊查詢的關鍵字
	 * @return 如果表中有資料,則所有的資料會封裝為VO物件而後利用List集合返回,<br>
	 * 如果沒有資料,那麼集合的長度為0(size() == 0,不是null)
	 * @throws Exception SQL執行異常
	 */
	public List<Emp> findAllSplitDetails(Integer currentPage, Integer lineSize, String column, String keyword)
			throws Exception;
}

一一實現這些方法(單方面的,暫不實現部門找到僱員,因為老師說現在理解不了...)

EmpDAOImpl.java

	@Override
	public Emp findByIdDetails(Integer id) throws Exception {
		Emp vo = null;

		String sql = " SELECT e.empno,e.ename,e.job,e.hiredate,e.sal,e.comm," + " m.empno 經理編號,m.ename 經理姓名,"
				+ " d.deptno 負責部門編號,d.dname 負責部門名稱,d.loc 負責部門地址 " + " FROM (emp e LEFT JOIN emp m ON e.mgr=m.empno) "
				+ " LEFT JOIN dept d ON e.dept=d.deptno " + " WHERE e.empno=? ";
		this.pstmt = this.conn.prepareStatement(sql);

		ResultSet rs = this.pstmt.executeQuery();
		if (rs.next()) {
			vo = new Emp();
			vo.setEmpno(rs.getInt(1));
			vo.setEname(rs.getString(2));
			vo.setJob(rs.getString(3));
			vo.setHiredate(rs.getDate(4));
			vo.setSal(rs.getDouble(5));
			vo.setComm(rs.getDouble(6));
			// 經理僱員資料
			Emp mgr = new Emp();
			mgr.setEmpno(rs.getInt(7));
			mgr.setEname(rs.getString(8));
			vo.setMgr(mgr);
			// 部門資料
			Dept dept = new Dept();
			dept.setDeptno(rs.getInt(9));
			dept.setDname(rs.getString(10));
			dept.setLoc(rs.getString(11));
			// 幫僱員找到部門
			vo.setDept(dept);
		}

		return vo;
	}

	@Override
	public List<Emp> findAllDetails() throws Exception {
		List<Emp> all = new ArrayList<Emp>();

		String sql = " SELECT e.empno,e.ename,e.job,e.hiredate,e.sal,e.comm," + " m.empno 經理編號,m.ename 經理姓名,"
				+ " d.deptno 負責部門編號,d.dname 負責部門名稱,d.loc 負責部門地址 " + " FROM (emp e LEFT JOIN emp m ON e.mgr=m.empno) "
				+ " LEFT JOIN dept d ON e.dept=d.deptno ";
		this.pstmt = this.conn.prepareStatement(sql);

		ResultSet rs = this.pstmt.executeQuery();
		while (rs.next()) {
			// 普通僱員資料
			Emp vo = new Emp();
			vo.setEmpno(rs.getInt(1));
			vo.setEname(rs.getString(2));
			vo.setJob(rs.getString(3));
			vo.setHiredate(rs.getDate(4));
			vo.setSal(rs.getDouble(5));
			vo.setComm(rs.getDouble(6));
			// 經理僱員資料
			Emp mgr = new Emp();
			mgr.setEmpno(rs.getInt(7));
			mgr.setEname(rs.getString(8));
			vo.setMgr(mgr);
			// 部門資料
			Dept dept = new Dept();
			dept.setDeptno(rs.getInt(9));
			dept.setDname(rs.getString(10));
			dept.setLoc(rs.getString(11));
			// 幫僱員找到部門
			vo.setDept(dept);
			// 將僱員加入List集合
			all.add(vo);
		}

		return all;
	}

	@Override
	public List<Emp> findAllSplitDetails(Integer currentPage, Integer lineSize, String column, String keyWord)
			throws Exception {
		List<Emp> all = new ArrayList<Emp>();

		String sql = " select e.empno,e.ename,e.job,e.hiredate,e.sal,e.comm, " + " m.empno 經理編號,m.ename 經理姓名, "
				+ " d.deptno 負責部門編號,d.dname 負責部門名稱,d.loc 負責部門地址  " + " FROM (emp e LEFT JOIN emp m ON e.mgr=m.empno) "
				+ " LEFT JOIN dept d ON e.dept=d.deptno " + " where e." + column + " like ? limit ?,? ";
		this.pstmt = this.conn.prepareStatement(sql);
		this.pstmt.setString(1, "%" + keyWord + "%");
		this.pstmt.setInt(2, (currentPage - 1) * lineSize);
		this.pstmt.setInt(3, lineSize);

		ResultSet rs = this.pstmt.executeQuery();
		while (rs.next()) {
			Emp vo = new Emp();
			vo.setEmpno(rs.getInt(1));
			vo.setEname(rs.getString(2));
			vo.setJob(rs.getString(3));
			vo.setHiredate(rs.getDate(4));
			vo.setSal(rs.getDouble(5));
			vo.setComm(rs.getDouble(6));
			// 經理僱員資料
			Emp mgr = new Emp();
			mgr.setEmpno(rs.getInt(7));
			mgr.setEname(rs.getString(8));
			vo.setMgr(mgr);
			// 部門資料
			Dept dept = new Dept();
			dept.setDeptno(rs.getInt(9));
			dept.setDname(rs.getString(10));
			dept.setLoc(rs.getString(11));
			// 幫僱員找到部門
			vo.setDept(dept);
			// 將僱員加入List集合
			all.add(vo);
		}

		return all;
	}

在服務層中實現這些方法

(1)IEmpService.java

package com.fs.service;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.fs.vo.Emp;
/**
 * 定義Emp表 業務層的執行標準,此類一定要負責資料庫的開啟和關閉操作
 * 此類可以通過DAOFactory類取得IEmpDAO的介面物件
 * @author 婉阿婉
 */
public interface IEmpService {
	public Emp getDetails(int ids) throws Exception;
	public List<Emp> listDetails() throws Exception; 
	public Map<String,Object> listDetails(int currentPage,int lineSize,String column,String keyWord) throws Exception; 
	/**
	 * 實現僱員資料的增加操作,本次操作要呼叫IEmpDAO介面的如下方法<br>
	 * <li>需要呼叫IEmpDAO.findById()方法,判斷要增加資料的id是否已經存在
	 * <li>如果要增加資料的id不存在則呼叫IEmpDAO.doCreate()方法,返回操作的結果
	 * @param vo 包含了要增加資料的VO物件
	 * @return 如果增加資料的ID重複即儲存失敗返回false,否則返回true
	 * @throws Exception SQL執行異常
	 */
	public boolean insert(Emp vo) throws Exception;

	/**
	 * 實現僱員資料的修改操作,本次要呼叫IEmpDAO.doUpdate()方法,本次修改屬於全部內容修改
	 * @param vo 包含了要修改的VO物件
	 * @return 修改成功返回true,否則返回false
	 * @throws Exception SQL執行異常
	 */
	public boolean update(Emp vo) throws Exception;

	/**
	 * 執行僱員資料的刪除操作,可以刪除多個僱員資訊,呼叫IEmpDAO.doRemoveBatch()方法
	 * @param ids 包含了所有要刪除資料的集合,其中沒有重複資料
	 * @return 刪除成功(要刪除條數==刪除條數)返回true,否則返回false
	 * @throws Exception SQL執行異常
	 */
	public boolean delete(Set<Integer> ids) throws Exception;

	/**
	 * 根據僱員編號查詢僱員的完整資訊,呼叫IEmpDAO.findById()方法
	 * @param ids 要查詢的僱員編號
	 * @return 找到了相應的僱員資訊則以VO物件返回,否則返回null
	 * @throws Exception SQL執行異常
	 */
	public Emp get(int ids) throws Exception;

	/**
	 * 查詢全部僱員資訊,呼叫IEmpDAO.findAll()方法
	 * @return 查詢結果以List集合的形式返回,如果沒有資料則集合長度為0
	 * @throws Exception SQL執行異常
	 */
	public List<Emp> list() throws Exception;

	/**
	 * 實現資料的模糊查詢與資料統計,要呼叫IEmpDAO介面的兩個方法:<br>
	 * <li>呼叫IEmpDAO.findAllSplit()方法,查詢出所有的表資料,返回List<Emp>;
	 * <li>呼叫IEmpDAO.getAllCount()方法,查詢所有的資料量,返回的Integer;
	 * @param currentPage 當前所在頁
	 * @param lineSize 每頁顯示的記錄數
	 * @param column 模糊查詢的資料列
	 * @param keyWord 模糊查詢的關鍵字
	 * @return 本方法由於需要返回多種資料型別,所以使用Map集合返回,由於型別不用一,所以所有value的型別設為Object<br>
	 * <li> key = allEmps,value = IEmpDAO.findAllSplit();返回結果:List<Emp>;
	 * <li> key = empCount,value = IempDAO.getAllCount();返回結果:Integer;
	 * @throws Exception
	 */
	public Map<String, Object> list(int currentPage, int lineSize, String column, String keyWord) throws Exception;
}


EmpServiceImpl.java

package com.fs.dao.impl;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.fs.dbc.DatabaseConnection;
import com.fs.factory.DAOFactory;
import com.fs.service.IEmpService;
import com.fs.vo.Emp;

public class EmpServiceImpl implements IEmpService {
	// 在這個類的物件內部就提供有一個數據庫連線類的例項化物件
	// 一但呼叫了DatabaseConnection,其就會進行資料庫連線
	private DatabaseConnection dbc = new DatabaseConnection();

	// 在進行insert過程中可能產生異常,但不管怎樣,最後一定要關閉資料庫,所以使用異常處理
	@Override
	public boolean insert(Emp vo) throws Exception {
		try {
			if (DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findById(vo.getEmpno()) == null) {
				return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).doCreate(vo);
			}
			return false; // 已經存在就返回false
		} catch (Exception e) {
			throw e; // 如果有問題,就直接向上拋
		} finally {
			this.dbc.close();
		}
	}

	@Override
	public boolean update(Emp vo) throws Exception {
		try {
			return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).doUpdate(vo);
		} catch (Exception e) {
			throw e; // 如果有問題,就直接向上拋
		} finally {
			this.dbc.close();
		}
	}

	@Override
	public boolean delete(Set<Integer> ids) throws Exception {
		try {
			return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).doRemoveBatch(ids);
		} catch (Exception e) {
			throw e; // 如果有問題,就直接向上拋
		} finally {
			this.dbc.close();
		}
	}

	@Override
	public Emp get(int ids) throws Exception {
		try {
			return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findById(ids);
		} catch (Exception e) {
			throw e; // 如果有問題,就直接向上拋
		} finally {
			this.dbc.close();
		}
	}

	@Override
	public List<Emp> list() throws Exception {
		try {
			return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findAll();
		} catch (Exception e) {
			throw e; // 如果有問題,就直接向上拋
		} finally {
			this.dbc.close();
		}
	}

	@Override
	public Map<String, Object> list(int currentPage, int lineSize, String column, String keyWord) throws Exception {
		try {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("allEmps", DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findAllSplit(currentPage,
					lineSize, column, keyWord));
			map.put("empCount", DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).getAllCount(column, keyWord));
			return map;
		} catch (Exception e) {
			throw e; // 如果有問題,就直接向上拋
		} finally {
			this.dbc.close();
		}
	}

	@Override
	public Emp getDetails(int id) throws Exception {
		try {
			return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findByIdDetails(id);
		} catch (Exception e) {
			throw e;
		} finally {
			this.dbc.close();
		}
	}

	@Override
	public List<Emp> listDetails() throws Exception {
		try {
			return DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findAllDetails();
		} catch (Exception e) {
			throw e; // 如果有問題,就直接向上拋
		} finally {
			this.dbc.close();
		}
	}

	@Override
	public Map<String, Object> listDetails(int currentPage, int lineSize, String column, String keyWord)
			throws Exception {
		try {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("allEmps", DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).findAllSplitDetails(currentPage,
					lineSize, column, keyWord));
			map.put("empCount", DAOFactory.getIEmpDAOInstance(this.dbc.getConnection()).getAllCount(column, keyWord));
			return map;
		} catch (Exception e) {
			throw e; // 如果有問題,就直接向上拋
		} finally {
			this.dbc.close();
		}
	}
}

測試:TestEmpSplitDetails.java

package com.fs.test;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.fs.factory.ServiceFactory;
import com.fs.vo.Emp;

public class TestEmpSplitDetails {
	public static void main(String[] args) {
		try {
			Map<String, Object> map = ServiceFactory.getIEmpServiceInstance().listDetails(1, 5, "ename", "三");
			int count = (Integer) map.get("empCount");
			System.out.println("總資料量:" + count);
			@SuppressWarnings("unchecked")
			List<Emp> all = (List<Emp>) map.get("allEmps");// 此處有警告,但此時的級數解決不了,自己去百度
			Iterator<Emp> iter = all.iterator();
			while (iter.hasNext()) {
				Emp vo = iter.next();
				System.out.println(vo.getEmpno() + "," + vo.getEname() + "," + vo.getMgr().getEname() + ","
						+ vo.getDept().getDname());
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

如果要想很好的完成開發需求,單表操作必須非常熟練!