詳解DAO模式(中)
上一節我們講解了DAO模式的大概框架,現在回到我之前說的:
“”、
現在來一一剖析這個程序的各個類:
(一)vo包:
(1)Emp類:主要以數據庫表列名爲參考寫了類的屬性,以及各個屬性的setter和getter方法。代碼如下:
package vo; import java.util.Date; public class Emp { private int empID; private String empName; private String job; private Date hireDate; private float salary; public void setEmpID(int empID) { this.empID = empID; } public int getEmpID() { return empID; } public void setEmpName(String empName) { this.empName = empName; } public String getEmpName() { return this.empName; } public void setJob(String job) { this.job = job; } public String getJob() { return this.job; } public void setHireDate(Date hireDate) { this.hireDate = hireDate; } public Date getHireDate() { return this.hireDate; } public void setSalary(float salary) { this.salary = salary; } public float getSalary() { return this.salary; } }
(二)dbc包:
(1)DatabaseConnection接口:它爲一個簡單的接口,在接口中抽象定義了getConnection()和close()兩個方法。代碼如下:
package dbc; import java.sql.Connection; public interface DatabaseConnection { public Connection getConnection(); public void close(); }
(2)OracleDatabaseConnection類:根據用戶實際使用的數據庫Oracle,用oracle定義的連接方式實現了DatabaseConnection接口的兩個方法。代碼如下:
package dbc; import java.sql.Connection; import java.sql.DriverManager; public class OracleDatabaseConnection implements DatabaseConnection { private static final String DRIVERCLASS = "oracle.jdbc.driver.OracleDriver"; private static final String URL = "jdbc:oracle:thin:@localhost:1521:ORCL"; private static final String USERNAME = "HYQ"; private static final String PASSWORD = "123456"; private Connection conn = null; public OracleDatabaseConnection() { try { Class.forName(DRIVERCLASS); } catch (ClassNotFoundException e) { e.printStackTrace(); } try { conn = DriverManager.getConnection(URL, USERNAME, PASSWORD); if (conn == null) { System.out.println("The \"conn\" is null !"); } else { System.out.println("conn --> " + conn); System.out.println(conn.hashCode()); } } catch (Exception e) { e.printStackTrace(); } } public Connection getConnection() { return this.conn; } public void close() { try { conn.close(); } catch (Exception e) { e.printStackTrace(); } } }
(3)OracleDatabaseConnectionFactory類:使用靜態方法返回一個OracleDatabaseConnection類的實例化對象。代碼如下:
package dbc; import dbc.OracleDatabaseConnection; public class OracleDatabaseConnectionFactory { public static OracleDatabaseConnection getOracleDatabaseConnection() { return new OracleDatabaseConnection(); } }
(三)dao包:
(1)IEmpDAO接口:它是一個簡單的接口,該接口裏面仍舊是抽象的方法,以及附帶一些參數說明。接口定義了doCreat()、findAll()、findByID()三個抽象方法。代碼如下:
package dao; import java.util.List; import vo.Emp; public interface IEmpDAO { /** * 數據庫的增加操作,一般以doXxx形式命名 * * @param emp * 要增加的數據對象 * @throws Exception * 把異常交給調用類處理 * @return 是否增加成功的標識 */ public boolean doCreat(Emp emp) throws Exception; /** * 查詢全部數據,一般以findXxx形式命名 * * @param keyword * 查詢的關鍵字 * @throws Exception * 把異常交給調用類處理 * @return 返回全部查詢結果,一個Emp對象表示EMP表的一行記錄 */ public List<Emp> findAll(String keyWord) throws Exception; /** * 根據僱員的ID號查詢僱員,返回一個Emp對象 * * @param empID * 僱員ID號 * @throws Exception * 把異常交給調用類處理 * @return 返回僱員的vo對象 */ public Emp findByID(int empID) throws Exception; }
(2)EmpDAOImpl類:實現的是IEmpDAO接口,具體定義了接口的三個方法,不過沒有獲取數據庫連接。代碼如下:
package dao; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; import vo.Emp; public class EmpDAOImpl implements IEmpDAO { private Connection conn = null; private PreparedStatement ps = null; public EmpDAOImpl(Connection conn) { this.conn = conn; } public boolean doCreat(Emp emp) throws Exception { boolean flag = false; String sql = "INSERT INTO EMP(EMPID,EMPNAME,JOB,HIREDATE,SALARY)VALUES(?,?,?,?,?)"; this.ps = this.conn.prepareStatement(sql); ps.setInt(1, emp.getEmpID()); ps.setString(2, emp.getEmpName()); ps.setString(3, emp.getJob()); ps.setDate(4, new java.sql.Date(emp.getHireDate().getTime())); ps.setFloat(5, emp.getSalary()); if (ps.executeUpdate() > 0) { flag = true; } this.ps.close(); return flag; } public List<Emp> findAll(String keyWord) throws Exception { List<Emp> all = new ArrayList<Emp>(); String sql = "SELECT EMPID,EMPNAME,JOB,HIREDATE,SALARY FROM EMP WHERE EMPNAME LIKE ? OR JOB LIKE ?"; this.ps = this.conn.prepareStatement(sql); ps.setString(1, "%" + keyWord + "%"); ps.setString(2, "%" + keyWord + "%"); ResultSet rs = this.ps.executeQuery(); Emp emp = null; while (rs.next()) { emp = new Emp(); emp.setEmpID(rs.getInt(1)); emp.setEmpName(rs.getString(2)); emp.setJob(rs.getString(3)); emp.setHireDate(rs.getDate(4)); emp.setSalary(rs.getFloat(5)); all.add(emp); } this.ps.close(); return all; } public Emp findByID(int empID) throws Exception { Emp emp = null; String sql = "SELECT EMPID,EMPNAME,JOB,HIREDATE,SALARY FROM EMP WHERE EMPID = ?"; this.ps = this.conn.prepareStatement(sql); ps.setInt(1, empID); ResultSet rs = ps.executeQuery(); if (rs.next()) { emp = new Emp(); emp.setEmpID(rs.getInt(1)); emp.setEmpName(rs.getString(2)); emp.setJob(rs.getString(3)); emp.setHireDate(rs.getDate(4)); emp.setSalary(rs.getFloat(5)); } this.ps.close(); return emp; } }
(3)EmpDAOProxy類:負責獲取和關閉數據庫,同時通過調用EmpDAOImpl類中的方法實現了IEmpDAO接口。代碼如下:
package dao; import java.util.List; import vo.Emp; import dbc.OracleDatabaseConnection; import dbc.OracleDatabaseConnectionFactory; public class EmpDAOProxy implements IEmpDAO { private OracleDatabaseConnection dbc = null; private IEmpDAO dao = null; public EmpDAOProxy() throws Exception { this.dbc = OracleDatabaseConnectionFactory .getOracleDatabaseConnection(); this.dao = new EmpDAOImpl(this.dbc.getConnection()); } public boolean doCreat(Emp emp) throws Exception { boolean flag = false; try { if (this.dao.findByID(emp.getEmpID()) == null) { flag = this.dao.doCreat(emp); } } catch (Exception e) { throw e; } finally { dbc.close(); } return flag; } public List<Emp> findAll(String keyWord) throws Exception { List<Emp> all = null; try{ all = this.dao.findAll(keyWord); }catch(Exception e){ throw e; }finally{ this.dbc.close(); } return all; } public Emp findByID(int empID) throws Exception { Emp emp = null; try{ emp = this.findByID(empID); }catch(Exception e){ throw e; }finally{ this.dbc.close(); } return emp; } }
(四)factory包:
(1)DAOFactory類:通過使用靜態方法返回EmpDAOProxy類的實例化對象。之所以使用靜態方法,是因爲不用new對象,大大節省了內存。在存在多個工廠類時效果更爲顯著。代碼如下:
package factory; import dao.EmpDAOProxy; import dao.IEmpDAO; public class DAOFactory { public static IEmpDAO getIEmpDAOInstance() throws Exception{ return new EmpDAOProxy(); } }
最後,在Java類或JSP中需要進行數據庫的操作時,就可以使用DAOFactory類得到一個IEmpDAO實例化對象,使用對象內置的方法進行操作即可。
好啦,那麼我們就來測試一下功能吧!
(1)添加功能,代碼如下:package test; import vo.Emp; import factory.DAOFactory; public class DAOTestInsert { public static void main(String[] args) throws Exception { Emp emp = null; for (int i = 1; i <= 10; i++) { emp = new Emp(); emp.setEmpID(i); emp.setEmpName("HYQ--" + i); emp.setJob("Student"); emp.setHireDate(new java.util.Date()); emp.setSalary(i * 1000); DAOFactory.getIEmpDAOInstance().doCreat(emp); } } }
效果測試圖:
在Myeclipse的console控制檯下執行成功的信息不斷的涌出來。
在Oracle的SQL developer的表中也出現了相關的數據,老夫數了一下,剛好10個。
(2)選擇功能,代碼如下:package test; import java.util.Iterator; import java.util.List; import vo.Emp; import factory.DAOFactory; public class DAOTestSelect { public static void main(String[] args) throws Exception { Emp emp = null; List<Emp> all = DAOFactory.getIEmpDAOInstance().findAll(""); Iterator<Emp> iter = all.iterator(); while (iter.hasNext()) { emp = iter.next(); System.out.println(emp.getEmpID() + " 、 " + emp.getEmpName() + " 、 " + emp.getJob() + " 、 " + emp.getHireDate() + " 、 " + emp.getSalary()); } } }
效果測試圖:
因爲關鍵字爲空,使用檢索出全部信息。
下一節我們講解JSP中調用DAO實現數據的插入和查詢 —— 詳解DAO模式(下)