DAO设计模式
1.认识DAO
DAO(Data Acess Object 数据库访问对象)的主要功能是操作数据库,所以DAO在标准开发架构中数据数据层,以下是标准开发的架构
- 客户层:目前使用B/S开发架构居多,客户可以通过浏览器访问
- 显示层:使用Vue框架、 React框架、 JSP/Servlet等进行页面展示
- 业务层:负责将DAO层的操作进行组合,形成一个完整的业务逻辑
- 数据层:提供原子性操作,比如增删查改
2.DAO各部分的详解
DAO的设计流程包括六个部分,如下:
1.DataBaseConnection
设计一个专门负责打开连接数据库和关闭数据库操作的类
命名规则: xxx.dbc.DataBaseConnection
2.VO
设计VO(值对象),其主要由属性,setter和getter组成与数据库中的字段进行对应。
命名规则:xxx.vo.ttt ; 其中ttt要和数据库中的表的名字一致
3.DAO
定义一系列原子性操作,比如增删查改,和实现业务的接口
命名规则:xxx.dao.I.xxx.DAO
4.Impl
设计DAO接口真正的实现类,完成具体的操作,但是不负责数据库的开关
命名规则:xxx.dao.imp.xxxDAOImpI
5.Proxy
Proxy代理类的实现,主要将以上四个部分组合起来,完成整个操作过程
命名规则:xxx.dao.Proxy.xxx.Proxy
6.Factory
Factory类主要用于获得DAO类的实例对象
命名规则:xxx.factory.DAOFactory
3.DAO设计模式流程
通过一个案例讲解DAO设计模式的流程
现在需要实现一个能够注册和查询工作者的案例(JDBC与DAO结合)
1.首先需要实现数据库的创建与表单的创建
/*======================= 删除数据库 =======================*/ DROP DATABASE IF EXISTS smile ; /*======================= 创建数据库 =======================*/ CREATE DATABASE smile ; /*======================= 使用数据库 =======================*/ USE smile ; /*======================= 删除数据表 =======================*/ DROP TABLE IF EXISTS worker ; /*======================= 创建数据表 =======================*/ CREATE TABLE worker( empno INT(4) PRIMARY KEY, ename VARCHAR(10), job VARCHAR(9), hiredate DATE, sal FLOAT(7,2) ) ; /*======================= 插入测试数据 =======================*/ INSERT INTO worker(empno,ename,job,hiredate,sal) VALUES (7369,'董鸣楠','销售','2003-10-09',1500.90) ; INSERT INTO worker(empno,ename,job,hiredate,sal) VALUES (8964,'李祺','分析员','2003-10-01',3000) ; INSERT INTO worker(empno,ename,job,hiredate,sal) VALUES (7698,'张惠','销售','2005-03-12',800) ; INSERT INTO worker(empno,ename,job,hiredate,sal) VALUES (7782,'杨军','分析员','2005-01-12',2500) ; INSERT INTO worker(empno,ename,job,hiredate,sal) VALUES (7762,'刘明','销售','2005-03-09',1000) ; INSERT INTO worker(empno,ename,job,hiredate,sal) VALUES (7839,'王月','经理','2006-09-01',2500) ;
2.定义VO类
package com.JavaWebDAO.vo; import java.util.Date ; //定义工人类 public class Worker { // 设置工人属性 private int empno ; private String ename ; private String job ; private Date hiredate ; private float sal ; // 配置setter函数 public void setEmpno(int empno){ this.empno = empno ; } public void setEname(String ename){ this.ename = ename ; } public void setJob(String job){ this.job = job ; } public void setHiredate(Date hiredate){ this.hiredate = hiredate ; } public void setSal(float sal){ this.sal = sal ; } // 配置getter函数 public int getEmpno(){ return this.empno ; } public String getEname(){ return this.ename ; } public String getJob(){ return this.job ; } public Date getHiredate(){ return this.hiredate ; } public float getSal(){ return this.sal ; } }
3.定义数据库连接类
package com.JavaWebDAO.db; import java.sql.Connection ; import java.sql.DriverManager ; public class DatabaseConnection { // 配置相关信息 private static final String DBDRIVER = "com.mysql.jdbc.Driver" ; private static final String DBURL = "jdbc:mysql://localhost:3306/smile" ; private static final String DBUSER = "root" ; private static final String DBPASSWORD = "357703" ; private Connection conn ; // 连接函数 public DatabaseConnection() throws Exception { // 加载类库 Class.forName(DBDRIVER) ; // 建立连接 this.conn = DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD) ; } // 返回连接对象 public Connection getConnection(){ return this.conn ; } // 断开连接函数 public void close() throws Exception { if(this.conn != null){ try{ this.conn.close() ; }catch(Exception e){ throw e ; } } } }
4.新建DAO接口
package com.JavaWebDAO.dao; import java.util.* ; import com.JavaWebDAO.vo.Worker; public interface IWorkerDAO { // 业务需求--注册员工 public boolean doCreate(Worker work) throws Exception ; // 业务需求--查询员工 public List<Worker> findAll(String keyWord) throws Exception ; // 业务需求--通过id查询员工 public Worker findById(int empno) throws Exception ; }
5.定义完DAO接口后就需要写好具体的实现类,实现类分为两种。
一种是真实实现类,一种是代理操作类。
真实实现类
package com.JavaWebDAO.dao.impI; import com.JavaWebDAO.dao.IWorkerDAO; import com.JavaWebDAO.vo.Worker; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.List; //真实实现类,实现IWorker中所有业务需求 public class WorkerDAOImpl implements IWorkerDAO { private Connection conn = null ; private PreparedStatement pstmt = null ; // 通过构造函数获取连接对象 public WorkerDAOImpl(Connection conn){ this.conn = conn ; } // 实现注册员工功能 public boolean doCreate(Worker work) throws Exception{ boolean flag = false ; String sql = "INSERT INTO worker(empno,ename,job,hiredate,sal) VALUES (?,?,?,?,?)" ; this.pstmt = this.conn.prepareStatement(sql) ; this.pstmt.setInt(1,work.getEmpno()) ; this.pstmt.setString(2,work.getEname()) ; this.pstmt.setString(3,work.getJob()) ; this.pstmt.setDate(4,new java.sql.Date(work.getHiredate().getTime())) ; this.pstmt.setFloat(5,work.getSal()) ; if(this.pstmt.executeUpdate() > 0){ flag = true ; } this.pstmt.close() ; return flag ; } // 实现查询员工的功能 public List<Worker> findAll(String keyWord) throws Exception{ List<Worker> all = new ArrayList<Worker>() ; String sql = "SELECT empno,ename,job,hiredate,sal FROM worker 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() ; Worker work = null ; while(rs.next()){ work = new Worker() ; work.setEmpno(rs.getInt(1)) ; work.setEname(((ResultSet) rs).getString(2)) ; work.setJob(rs.getString(3)) ; work.setHiredate(rs.getDate(4)) ; work.setSal(rs.getFloat(5)) ; all.add(work) ; } this.pstmt.close() ; return all ; } // 实现通过id查询员工的功能 public Worker findById(int empno) throws Exception{ Worker emp = null ; String sql = "SELECT empno,ename,job,hiredate,sal FROM worker WHERE empno=?" ; this.pstmt = this.conn.prepareStatement(sql) ; this.pstmt.setInt(1,empno) ; ResultSet rs = this.pstmt.executeQuery() ; if(rs.next()){ emp = new Worker() ; 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 ; } }
代理操作类
package com.JavaWebDAO.dao.proxy; import com.JavaWebDAO.dao.IWorkerDAO; import com.JavaWebDAO.dao.impI.WorkerDAOImpl; import com.JavaWebDAO.db.DatabaseConnection; import com.JavaWebDAO.vo.Worker; import java.util.List; //代理操作IWorkerDAo中的业务需求 public class WorkerDAOProxy implements IWorkerDAO { private DatabaseConnection db = null ; private IWorkerDAO dao = null ; // 代理建立连接数据库 public WorkerDAOProxy() throws Exception { this.db = new DatabaseConnection() ; this.dao = new WorkerDAOImpl(this.db.getConnection()) ; } // 代理实现注册功能 public boolean doCreate(Worker work) throws Exception{ boolean flag = false ; try{ if(this.dao.findById(work.getEmpno()) == null){ flag = this.dao.doCreate(work) ; } }catch(Exception e){ throw e ; }finally{ this.db.close() ; } return flag ; } // 代理实现查询用户功能 public List<Worker> findAll(String keyWord) throws Exception{ List<Worker> all = null ; try{ all = this.dao.findAll(keyWord) ; }catch(Exception e){ throw e ; }finally{ this.db.close() ; } return all ; } // 代理通过id查询用户的功能 public Worker findById(int empno) throws Exception { Worker emp = null; try { emp = this.dao.findById(empno); } catch (Exception e) { throw e; } finally { this.db.close(); } return emp; } }
代理类只是调用了真实类中的方法,但是代理类可以让代码开发的结构更加清晰
6.定义工厂类
package com.JavaWebDAO.factory; import com.JavaWebDAO.dao.IWorkerDAO; import com.JavaWebDAO.dao.proxy.WorkerDAOProxy; public class DAOFactory { // 通过工厂获取代理类的实例 public static IWorkerDAO getIWorkerDAOInstance() throws Exception{ return new WorkerDAOProxy() ; } }
设计完所有类和接口后,为了保证定义后功能可用,则需要做一个测试类,来测试所有功能是否能够正常使用
package com.lzl.dao.test ; import com.lzl.factory.DAOFactory ; import com.lzl.vo.* ; public class TestdoCreate{ public static void main(String args[]) throws Exception{ Worker work = null ; work = new Worker() ; work.setEmpno(1000) ; work.setEname("SMILE") ; work.setJob("程序员 " ) ; work.setHiredate(new java.util.Date()) ; work.setSal(10000) ; DAOFactory.getIWorkerDAOInstance().doCreate(work) ; } }
package com.lzl.dao.test ; import java.util.* ; import com.lzl.factory.DAOFactory ; import com.lzl.vo.* ; public class TestfindAll{ public static void main(String args[]) throws Exception{ List<Worker> all = DAOFactory.getIWorkerDAOInstance().findAll("") ; Iterator<Worker> iter = all.iterator() ; while(iter.hasNext()){ Worker work = iter.next() ; System.out.println(work.getEmpno() + "、" + work.getEname() + " 、 " + work.getJob()+ "、"+work.getHiredate() + " 、 "+work.getSal()) ; } } }
整体项目结构
编辑
这样DAO层就开发完毕了