DAo设计模式1.docx
《DAo设计模式1.docx》由会员分享,可在线阅读,更多相关《DAo设计模式1.docx(17页珍藏版)》请在冰点文库上搜索。
![DAo设计模式1.docx](https://file1.bingdoc.com/fileroot1/2023-6/28/714efab1-10f4-4167-993a-3eb1f24c6b9f/714efab1-10f4-4167-993a-3eb1f24c6b9f1.gif)
DAo设计模式1
DAO设计模式
DAO设计模式简介
DAO(DataAccessObject数据访问对象)主要功能是数据操作,在程序开发架构中属于数据层的操作,程序的标准开发架构如下:
在整个DAO中实际上是以接口为操作标准,即客户端依靠DAO实现的接口进行操作,而服务器端要将接口进行具体的实现。
由以下几个部分组成:
包的命名:
✧数据库连接:
xxx.dbc.DatabaseConection
✧DAO接口:
xxx.dao.IXxxDAO
✧DAO接口真实实现类:
xxx.dao.impl.XxxDAOImpl
✧DAO接口代理实现类:
xxx.dao.proxy.XxxDAOProxy
✧VO类:
xxx.vo.Xxx,VO的命名要与表的命名一致
✧工厂类:
xxx.factory.DAOFactory
DAO开发
DAO的开发完全围绕数据库进行,使用如下表
数据库创建脚本:
/*=======================删除数据库=======================*/
DROPDATABASEIFEXISTShbmu;
/*=======================创建数据库=======================*/
CREATEDATABASEhbmu;
/*=======================使用数据库=======================*/
USEhbmu;
/*=======================删除数据表=======================*/
DROPTABLEIFEXISTSemp;
/*=======================创建数据表=======================*/
CREATETABLEemp(
empnoINT(4)PRIMARYKEY,
enameVARCHAR(10),
jobVARCHAR(9),
hiredateDATE,
salFLOAT(7,2)
);
首先定义VO类,VO类的名称与表的名称一致,但是要注意类的命名规范---单词的开头首字母大写:
定义对应的VO类----Emp.java
packagecn.edu.hbmu.vo;
importjava.util.Date;
publicclassEmp{
privateintempno;
privateStringename;
privateStringjob;
privateDatehiredate;
privatefloatsal;
publicintgetEmpno(){
returnempno;
}
publicvoidsetEmpno(intempno){
this.empno=empno;
}
publicStringgetEname(){
returnename;
}
publicvoidsetEname(Stringename){
this.ename=ename;
}
publicStringgetJob(){
returnjob;
}
publicvoidsetJob(Stringjob){
this.job=job;
}
publicDategetHiredate(){
returnhiredate;
}
publicvoidsetHiredate(Datehiredate){
this.hiredate=hiredate;
}
publicfloatgetSal(){
returnsal;
}
publicvoidsetSal(floatsal){
this.sal=sal;
}
}
简单的VO类,定义了属性、getter、setter方法。
日期使用的是java.util.Date;
定义
数据库连接类------DatabaseConnection.java
packagecn.edu.hbmu.dbc;
importjava.sql.Connection;
importjava.sql.DriverManager;
importjava.sql.SQLException;
publicclassDatabaseConnection{
privatestaticfinalStringDBDRIVER="org.gjt.mm.mysql.Driver";
privatestaticfinalStringDBURL="jdbc:
mysql:
//localhost:
3306/hbmu";
privatestaticfinalStringDBUSER="root";
privatestaticfinalStringDBPASSWORD="123";
privateConnectionconn;
publicDatabaseConnection()throwsException{
Class.forName(DBDRIVER);this.conn=DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD);
}
publicConnectiongetConnection(){
returnthis.conn;
}
publicvoidclose()throwsException{
if(this.conn!
=null){
try{
this.conn.close();
}catch(Exceptione){
throwe;
}
}
}
}
在执行数据库连接和关闭中,由于可能出现意外情况而导致无法操作成功时,所有的异常将统一交给调用处处理。
如果要适用不同的数据库,可以将可能变化的地方听过接口实现,然后根据不同的数据库定义不同的子类,通过工厂类完成调用
DAO接口DAO接口:
xxx.dao.IXxxDAO
packagecn.edu.hbmu.dao;
importjava.util.List;
importcn.edu.hbmu.vo.Emp;
publicinterfaceIEmpDAO{
/**
*数据的增加操作,一般以doXxx的方式命名
*@paramemp要增加的数据对象
*@return是否增加成功的标记
*@throwsException有异常交给被调用处处理
*/
publicbooleandoCreate(Empemp)throwsException;
/**
*查询全部的数据(多条记录),一般以findXxx的方式命名或getXxx
*@paramkeyWord查询关键字
*@return返回全部的查询结果,每一个Emp对象表示表的一行记录
*@throwsException有异常交给被调用处处理
*/
publicListfindAll(StringkeyWord)throwsException;
/**
*根据雇员编号查询雇员信息
*@paramempno雇员编号
*@return雇员的VO对象
*@throwsException有异常交给被调用处处理
*/
publicEmpfindById(intempno)throwsException;
}
DAO接口定义完成后需要具体的实现类,有两种:
1.真实实现类
2.代理实现类
DAO接口真实实现类:
xxx.dao.impl.XxxDAOImpl
真实实现类主要负责具体的数据库操作,在操作时为了性能和安全使用PreparedStatement接口完成。
packagecn.hbmu.edu.dao.impl;
importjava.sql.Connection;
importjava.sql.PreparedStatement;
importjava.sql.ResultSet;
importjava.util.ArrayList;
importjava.util.List;
importcn.edu.hbmu.dao.IEmpDAO;
importcn.edu.hbmu.vo.Emp;
publicclassEmpDAOImplimplementsIEmpDAO{
privateConnectionconn=null;//数据库连接对象
privatePreparedStatementpstmt=null;//数据库操作对象
publicEmpDAOImpl(Connectionconn){//构造方法接收外部传递来的数据库连接的实例化对象
this.conn=conn;//取得数据库连接
}
publicbooleandoCreate(Empemp)throwsException{
booleanflag=false;//定义标志位
Stringsql="insertintoemp(empno,ename,job,hiredate,sal)values(?
?
?
?
?
)";
this.pstmt=this.conn.prepareStatement(sql);//实例化预处理对象
this.pstmt.setInt(1,emp.getEmpno());//设置empno
this.pstmt.setString(2,emp.getEname());
this.pstmt.setString(3,emp.getJob());
this.pstmt.setDate(4,newjava.sql.Date(emp.getHiredate().getTime()));
//设置hiredate对象,PreparedStatement对象的setDate方法是用的是SQLDATEvalue,需要转换java.util.Date.getTime()
this.pstmt.setFloat(5,emp.getSal());
if(this.pstmt.executeUpdate()>0){//更新记录的行数大于0
flag=true;//修改标志位
}
this.pstmt.close();//关闭PreparedStatement对象
returnflag;
}
publicListfindAll(StringkeyWord)throwsException{
Listall=newArrayList();//定义集合,接收全部数据
Stringsql="selectempno,ename,job,hiredate,salfromempwhereenamelike?
orjoblike?
";
this.pstmt=this.conn.prepareStatement(sql);//实例化预处理对象
this.pstmt.setString(1,"%"+keyWord+"%");//设置查询的关键字
this.pstmt.setString(2,"%"+keyWord+"%");//
ResultSetrs=this.pstmt.executeQuery();//执行查询操作
while(rs.next()){//依次取出每一条数据
Empemp=newEmp();//实例化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();
returnall;
}
publicEmpfindById(intempno)throwsException{
Empemp=null;
Stringsql="SELECTempno,ename,job,hiredate,salFROMempWHEREempno=?
";
this.pstmt=this.conn.prepareStatement(sql);
this.pstmt.setInt(1,empno);
ResultSetrs=this.pstmt.executeQuery();
if(rs.next()){
emp=newEmp();
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();
returnemp;
}
}
在真实的实现类中,根本没有处理数据库的打开和连接操作,只是通过构造方法取得了数据库的连接,而真正负责打开和关闭数据库的操作由代理类完成。
DAO接口代理实现类:
xxx.dao.proxy.XxxDAOProxy
packagecn.edu.hbmu.dao.proxy;
importjava.sql.ResultSet;
importjava.util.ArrayList;
importjava.util.List;
importcn.edu.hbmu.dao.IEmpDAO;
importcn.edu.hbmu.dbc.DatabaseConnection;
importcn.edu.hbmu.vo.Emp;
importcn.hbmu.edu.dao.impl.EmpDAOImpl;
publicclassEmpDAOProxyimplementsIEmpDAO{
privateDatabaseConnectiondbc=null;//定义数据库的连接类
privateIEmpDAOdao=null;//声明DAO对象
publicEmpDAOProxy()throwsException{//在构造方法中实例化连接,同时实例化DAO对象
this.dbc=newDatabaseConnection();//连接数据库
this.dao=newEmpDAOImpl(this.dbc.getConnection());//实例化真实主题类
}
publicbooleandoCreate(Empemp)throwsException{
booleanflag=false;
try{
if(this.dao.findById(emp.getEmpno())==null){//如果要插入的雇员编号不存在
flag=this.dao.doCreate(emp);//调用真实主题操作
}
}catch(Exceptione){//有异常交给被调用处
throwe;
}finally{
this.dbc.close();//关闭数据库
}
returnflag;
}
publicListfindAll(StringkeyWord)throwsException{
Listall=null;
try{
all=this.dao.findAll(keyWord);
}catch(Exceptione){
throwe;
}finally{
this.dbc.close();
}
returnall;
}
publicEmpfindById(intempno)throwsException{
Empemp=null;
try{
emp=this.dao.findById(empno);
}catch(Exceptione){
throwe;
}finally{
this.dbc.close();
}
returnemp;
}
}
在代理类的构造方法中实例化了数据库连接类的对象以及真实实现类,而在代理中的各个方法只是调用了真实主题实现类中的相应方法。
异常处理格式:
try{
XXXXXXXXXXXXXXXXXXXXXXXXXXX
}catch(Exceptione){
throwe;
}finally{
this.dbc.close();
}
工厂类:
xxx.factory.DAOFactory
packagecn.edu.hbmu.factory;
importcn.edu.hbmu.dao.IEmpDAO;
importcn.edu.hbmu.dao.proxy.EmpDAOProxy;
publicclassDAOFactory{
publicstaticIEmpDAOgetIEmpDAOInstance()throwsException{
returnnewEmpDAOProxy();
}
}
本工厂类中的功能就是直接返回DAO接口的实例化对象,以后的客户端直接通过工厂类就可以取得DAO接口的实例化对象。
测试DAO插入类--------------TestDAOInsert
packagecn.edu.hbmu.dao.test;
importcn.edu.hbmu.factory.DAOFactory;
importcn.edu.hbmu.vo.Emp;
publicclassTestDAOInsert{
publicstaticvoidmain(String[]args)throwsException{
Empemp=null;
for(intx=0;x<5;x++){
emp=newEmp();
emp.setEmpno(1000+x);
emp.setEname("刘向阳-"+x);
emp.setJob("程序员-"+x);
emp.setHiredate(newjava.util.Date());
emp.setSal(500*x);
DAOFactory.getIEmpDAOInstance().doCreate(emp);
}
}
}
测试查询操作--------------TestDAOSelect
packagecn.edu.hbmu.dao.test;
importjava.util.Iterator;
importjava.util.List;
importcn.edu.hbmu.factory.DAOFactory;
importcn.edu.hbmu.vo.Emp;
publicclassTestDAOSelect{
publicstaticvoidmain(Stringargs[])throwsException{
Listall=DAOFactory.getIEmpDAOInstance().findAll("");
Iteratoriter=all.iterator();
while(iter.hasNext()){
Empemp=iter.next();
System.out.println(emp.getEmpno()+"、"+emp.getEname()+"-->"+emp.getJob());
}
}
}
完全以对象的形式操作数据库,而在客户端的代码明显减少。
DAO操作只是提供一个数据的操作平台,不管application程序还是web程序中,此DAO程序都不用做任何修改,可使得程序达到很好的重用性。
JSP调用DAO
1.添加雇员
<%@pagecontentType="text/html"pageEncoding="GBK"%>
雇员编号:
雇员姓名:
雇员职位:
雇佣日期:
基本工资:
完成增加雇员的操作
<%@pagecontentType="text/html"pageEncoding="GBK"%>
<%@pageimport="cn.edu.hbmu.factory.*,cn.edu.hbmu.vo.*"%>
<%@pageimport="java.text.*"%>
<%
request.setCharacterEncoding("GBk");
%>
<%
Empemp=newEmp();
emp.setEmpno(Integer.parseInt(request.getParameter("empno")))