DAO的開發徹底圍繞着數據進行,先在數據庫中準備幾個要用到的表:java
sqlcreate table emp ( empno int(4) PRIMARY KEY, ename varchar(10), job varchar(9), hiredate date, sal float(7,2) );
根據表中的字段創建對應的VO類:mysql
javapackage temp.vo; import java.util.Date; /** * Created by mcbird on 14/11/20. */ public class Emp { private int empno; private String ename; private String job; private Date hiredate; private float sal; 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 Date getHiredate() { return hiredate; } public void setHiredate(Date hiredate) { this.hiredate = hiredate; } public float getSal() { return sal; } public void setSal(float sal) { this.sal = sal; } public int getEmpno() { return empno; } public void setEmpno(int empno) { this.empno = empno; } }
能夠看到,VO類中只包含getter和setter方法。定義完VO類以後,接下來定義一個DatebaseConnection類,用來完成數據庫的打開及關閉操做。sql
考慮到實踐當中,有可能使用不一樣的數據庫,所用,咱們須要寫一個通用接口,以及相應的數據庫的實現類。數據庫
javapackage temp.dbc; import java.sql.Connection; /** * Created by mcbird on 14/11/20. */ public interface DatebaseConnection { public Connection getConnection() throws Exception; // 取得數據庫鏈接 public void close() throws Exception; //關閉數據庫鏈接 }
經過這樣一個接口,可以更好的鬆耦合、更抽象。設計模式
javapackage temp.dbc.impl; import temp.dbc.DatebaseConnection; import java.sql.Connection; import java.sql.DriverManager; /** * Created by mcbird on 14/11/20. */ public class MySQLDatabaseConnection implements DatebaseConnection { private static final String DBDRIVER = "org.gjt.mm.mysql.Driver"; private static final String DBURL = "jdbc://localhost:3306/temp"; private static final String DBUSER = "root"; private static final String DBPASSWORD = "cloudSoft@Skybility"; private Connection conn = null; @Override public Connection getConnection() throws Exception { try { Class.forName(DBDRIVER); this.conn = DriverManager.getConnection(DBURL, DBUSER, DBPASSWORD); }catch (Exception e) { throw e; } return this.conn; } @Override public void close() throws Exception { if(this.conn != null) { try { this.conn.close(); } catch (Exception e) { throw e; } } } }
這是針對MySQL的一個實現類,還能夠針對不一樣的數據庫編寫不一樣的實現類。ide
在DAO設計模式中,最重要的就是定義DAO接口,在定義DAO接口以前必須對業務進行詳細的分析,要清楚地知道一張表在整個系統中應該具有何種功能。測試
javapackage temp.dao; import temp.vo.Emp; import java.util.List; /** * Created by mcbird on 14/11/20. */ public interface IEmpDAO { /** * 數據的增長操做 * @param emp 要增長的數據對象 * @return 是否成功增長標誌 */ public boolean doCreate(Emp emp) throws Exception; /** * 查詢所有數據 * @param keyWord * @return * @throws Exception */ public List<Emp> findAll(String keyWord) throws Exception; /** * 根據編號查詢僱員信息 * @param empno * @return * @throws Exception */ public Emp findById(int empno) throws Exception; }
javapackage temp.dao.impl; import temp.dao.IEmpDAO; import temp.vo.Emp; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; /** * Created by mcbird on 14/11/20. */ public class EmpDAOImpl implements IEmpDAO { private Connection conn = null; private PreparedStatement pstmt = null; //數據庫操做對象 public EmpDAOImpl(Connection conn) { this.conn = conn; } @Override public boolean doCreate(Emp emp) throws Exception { boolean flag = false; String sql = "insert int emp (empno,ename,job,hiredate,sal) values (?,?,?,?,?)"; this.pstmt = this.conn.prepareStatement(sql); this.pstmt.setInt(1, emp.getEmpno()); this.pstmt.setString(2, emp.getEname()); this.pstmt.setString(3, emp.getJob()); this.pstmt.setDate(4, new Date(emp.getHiredate().getTime())); this.pstmt.setFloat(5, emp.getSal()); if(this.pstmt.executeUpdate() > 0) { //更新記錄的行數大於0 flag = true; } this.pstmt.close(); return flag; } @Override public List<Emp> findAll(String keyWord) throws Exception { List<Emp> all = new ArrayList<Emp>(); String sql = "select empno,ename,job,hiredate,sal from emp where ename like ? or job like ?"; this.pstmt = this.conn.prepareStatement(sql); this.pstmt.setString(1, "%" + keyWord + "%"); this.pstmt.setString(2, "%" + keyWord + "%"); ResultSet rs = this.pstmt.executeQuery(); Emp emp = null; while (rs.next()) { emp = new Emp(); emp.setEmpno(rs.getInt(1)); emp.setEname(rs.getString(2)); emp.setJob(rs.getString(3)); emp.setHiredate(rs.getDate(4)); emp.setSal(rs.getFloat(5)); all.add(emp); } this.pstmt.close(); return all; } @Override public Emp findById(int empno) throws Exception { Emp emp = null; String sql = "select empno,ename,job,hiredate,sal from emp where empno=?"; this.pstmt = this.conn.prepareStatement(sql); this.pstmt.setInt(1, empno); ResultSet rs = this.pstmt.executeQuery(); if(rs.next()) { emp = new Emp(); emp.setEmpno(rs.getInt(1)); emp.setEname(rs.getString(2)); emp.setJob(rs.getString(3)); emp.setHiredate(rs.getDate(4)); emp.setSal(rs.getFloat(5)); } this.pstmt.close(); return emp; } }
能夠發現,在這個實現類中,根本沒有數據庫的打開和連接操做,只是經過構造方法取得了數據庫的連接,那麼真正負責打開和關閉的操做是由誰來完成的呢?答案是,代理類。this
javapackage temp.dao.proxy; import temp.dao.IEmpDAO; import temp.dao.impl.EmpDAOImpl; import temp.dbc.DatebaseConnection; import temp.dbc.impl.MySQLDatabaseConnection; import temp.vo.Emp; import java.util.List; /** * Created by mcbird on 14/11/20. */ public class EmpDAOProxy implements IEmpDAO { private DatebaseConnection dbc = null; private IEmpDAO dao = null; public EmpDAOProxy() throws Exception { this.dbc = new MySQLDatabaseConnection(); this.dao = new EmpDAOImpl(this.dbc.getConnection()); } @Override public boolean doCreate(Emp emp) throws Exception { boolean flag = false; try { if (this.dao.findById(emp.getEmpno()) == null) { flag = this.dao.doCreate(emp); } } catch (Exception e) { throw e; } finally { this.dbc.close(); } return flag; } @Override public List<Emp> findAll(String keyWord) throws Exception { List<Emp> all = null; try { all = this.findAll(keyWord); } catch (Exception e) { throw e; } finally { this.dbc.close(); } return all; } @Override public Emp findById(int empno) throws Exception { Emp emp = null; try { emp = this.dao.findById(empno); } catch (Exception e) { throw e; } finally { this.dbc.close(); } return emp; } }
能夠發現,在代理類的構造方法中實例化了數據庫鏈接類的對象以及DAO的實現類,而在代理中的各個方法只是調用了真實DAO實現類的相應方法。在代理類完成之後,最後還須要編寫工廠類,以下降代碼間的耦合度。設計
工廠類的功能就是直接返回DAO接口的實例化對象,這樣客戶端就能夠直接經過工廠類取得DAO接口的實例化對象。代理
javapackage temp.dao.factory; import temp.dao.IEmpDAO; import temp.dao.proxy.EmpDAOProxy; /** * Created by mcbird on 14/11/20. */ public class DAOFactory { public static IEmpDAO getIEmpDAOInstance() throws Exception { return new EmpDAOProxy(); } }
javapackage temp.test; import temp.dao.factory.DAOFactory; import temp.vo.Emp; import java.util.Date; /** * Created by mcbird on 14/11/20. */ public class TestDAOInsert { public static void main(String[] args) throws Exception { Emp emp = null; for(int x = 0; x < 5; x++) { emp = new Emp(); emp.setEmpno(1000 + x); emp.setEname("McBird_" + x); emp.setJob("Singer_" + x); emp.setHiredate(new Date()); emp.setSal(100 * x); DAOFactory.getIEmpDAOInstance().doCreate(emp); } } }