详解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模式(下)