DAO程序开发架构:
客户层(client)=》显示层(Jsp/Servlet)=》业务层(BO)=》数据层(DAO)=》资源层(DataBase)
1.在Java EE中实现DAO模式,主要分为6个模块,具体如下:
(1) 数据库连接类:专门负责数据库的打开与关闭操作
(2) VO类(value object值对象):主要由属性、setter、getter方法组成,VO类中的属性与表中的字段相对应,每一个VO类的对象都表示表中的每一条数据。实际上VO类就是一个JavaBean。
(3) DAO接口:主要定义操作的接口,定义一系列数据库的原子性操作标准,如增删改查(只不过是接口,定义的都是抽象方法。建议看看Java继承与接口,涉及到编写接口)
(4) Impl:DAO接口真实实现类:完成数据库的各项操作,但是不负责数据库的打开和关闭
(5) Proxy:DAO 代理实现类:主要完成数据库的打开和关闭,并且调用真实对象的操作
(6)Factory:DAO工厂类:通过工厂类取得一个DAO的实例化对象
- 对于包的命名:
在使用DAO时对包有严格的命名
- 数据库连接: xxx.dbc.DatabaseConnection
- DAO接口: xxx.dao.IXxxDAO
- DAO接口真实实现类:xxx.dao.impl.XxxDAOImpl
- DAO接口代理实现类:xxx.dao.proxy.XxxDAOProxy
- VO类: xxx.vo.Xxx, VO命名要与表的命名一致
- 工厂类:xxx.factory.DAOFactory.
3.一个小实例
步骤一:创建数据库,此处用的mysql数据库
/*======================= 删除数据库 =======================*/
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) ;
创建成功后会有一个含有worker表的smile数据库
步骤二:定义VO类
package com.lqc.vo;
import java.util.Date;
public class Worker {
private int empno;
private String ename;
private String job;
private Date hiredate;
private float sal;
public int getEmpno() {
return empno;
}
public void setEmpno(int empno) {
this.empno = empno;
}
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;
}
}
步骤三:定义一个数据库连接类
package com.lqc.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class DatabaseConnection {
private static final String DBDRIVER="com.mysql.cj.jdbc.Driver";
private static final String DBURL="jdbc:mysql://localhost:3306/smile?characterEncoding=utf8&serverTimezone=UTC";
private static final String DBUSER="root";
private static final String DBPASSWORD="123456";
private Connection conn;
public DatabaseConnection() throws Exception {
//加载数据库驱动
System.out.println("1");
Class.forName(DBDRIVER);
System.out.println("2");
//进行数据库连接
this.conn= DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD);
System.out.println("数据库连接成功");
}
//取得数据库连接
public Connection getConnection(){
return conn;
}
//关闭数据库连接
public void close() throws Exception {
if(this.conn!=null){
try {
this.conn.close();
} catch (SQLException e) {
throw e;
}
}
}
}
步骤四:新建DAO接口
package com.lqc.dao;
import com.lqc.vo.Worker;
import java.util.List;
public interface IWorkerDAO {
public boolean doCreate(Worker worker) throws Exception;
public List<Worker> findALL(String keyWord) throws Exception;
public Worker findById(int empno) throws Exception;
}
在定义接口的时候,接口的前面加了一个I,这个是接口的命名规范,表示这是一个接口。
步骤五:DAO接口定义完成之后,就要写具体的实现类。分为2种,一种是真实实现类,还有一种是代理操作类。真实实现类负责数据库的具体操作,不包括数据库的打开与关闭;代理操作类真正负责的就是数据库的打开与关闭。
真实实现类
package com.lqc.dao.impl;
import com.lqc.dao.IWorkerDAO;
import com.lqc.vo.Worker;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class WorkerDAOImpl implements IWorkerDAO {
private Connection conn =null;
private PreparedStatement pstmt=null;
//通过构造方法取得数据库连接
public WorkerDAOImpl(Connection conn){
this.conn=conn;
}
//数据增加操作
@Override
public boolean doCreate(Worker worker) throws Exception {
boolean flag=false;
//添加sql语句
String sql="INSERT INTO worker(empno,ename,job,hiredate,sal) VALUES (?,?,?,?,?)";
//实例化PrepareStatement对象
this.pstmt=this.conn.prepareStatement(sql);
this.pstmt.setInt(1, worker.getEmpno());
this.pstmt.setString(2,worker.getEname());
this.pstmt.setString(3,worker.getJob());
this.pstmt.setString(4, String.valueOf(new Date(worker.getHiredate().getTime())));
this.pstmt.setFloat(5,worker.getSal());
if(this.pstmt.executeUpdate()>0){
flag=true;
}
this.pstmt.close();
return flag;
}
//查询操作
@Override
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 worker=null;
//遍历集合取出每一条数据
while(rs.next()){
worker=new Worker();
worker.setEmpno(rs.getInt(1));
worker.setEname(rs.getString(2));
worker.setJob(rs.getString(3));
worker.setHiredate(rs.getDate(4));
worker.setSal(rs.getFloat(5));
all.add(worker);
}
this.pstmt.close();
return all;
}
//根据编号查询操作
@Override
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.lqc.dao.proxy;
import com.lqc.dao.IWorkerDAO;
import com.lqc.dao.impl.WorkerDAOImpl;
import com.lqc.db.DatabaseConnection;
import com.lqc.vo.Worker;
import java.util.List;
public class WorkerDAOProxy implements IWorkerDAO {
private DatabaseConnection db=null; //数据库连接对象
private IWorkerDAO dao=null; //DAO对象
public WorkerDAOProxy() throws Exception { //实例化数据库连接和DAO对象
this.db=new DatabaseConnection(); //连接数据库
this.dao=new WorkerDAOImpl(this.db.getConnection()); //实例化真实操作类对象
}
@Override
public boolean doCreate(Worker worker) throws Exception {
boolean flag=false;
try{
//如果要插入的雇员编号不存在
if(this.dao.findById(worker.getEmpno())==null){
//真实操作类调用
flag=this.dao.doCreate(worker);
}
}catch (Exception e){
throw e;
}finally {
this.db.close();
}
return flag;
}
@Override
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;
}
@Override
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 null;
}
}
代理操作类中的方法是调用真实实现类中的相应方法。同时这个代理类也能够使代码开发结构更清晰。
步骤六:编写工厂类
package com.lqc.factory;
import com.lqc.dao.IWorkerDAO;
import com.lqc.dao.proxy.WorkerDAOProxy;
public class DAOFactory {
public static IWorkerDAO getIWorkerDAOInstance() throws Exception {
return new WorkerDAOProxy();
}
}
这个类的功能就是直接返回DAO接口的实例化对象,也就是说在客户端直接通过工厂类就可以获取DAO接口的实例化对象。
接下来测试一下。
测试查询功能
package com.lqc.dao.test;
import com.lqc.factory.DAOFactory;
import com.lqc.vo.Worker;
import java.util.Iterator;
import java.util.List;
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 worker=iter.next();
System.out.println(worker.getEmpno()+","+worker.getEname()+","+worker.getJob()+","+
worker.getHiredate()+","+worker.getSal());
}
}
}
接下来测试web程序的查询
编写work_list.jsp
<%--
Created by IntelliJ IDEA.
User: l1957
Date: 2021/1/20
Time: 11:31
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=GBK" language="java" pageEncoding="GBK" %>
<%@ page import="com.lqc.factory.*,com.lqc.vo.*"%>
<%@ page import="java.util.*"%>
<html>
<head>
<title>work list</title>
</head>
<% request.setCharacterEncoding("GBK");%>
<body>
<%
String keyWord=request.getParameter("kw");
out.println(keyWord);
if(keyWord==null){
keyWord="";
}
List<Worker> all=DAOFactory.getIWorkerDAOInstance().findALL(keyWord);
Iterator<Worker> iter=all.iterator();
%>
<center>
<form action="work_list.jsp" method="post">
请输入查询关键字:<input type="text" name="kw">
<input type="submit" value="查询">
</form>
<table border="1" width="80%">
<tr>
<td>编号</td>
<td>姓名</td>
<td>工作</td>
<td>工作日期</td>
<td>工资</td>
</tr>
<%
while(iter.hasNext()){
Worker worker=iter.next();
%>
<tr>
<td><%=worker.getEmpno()%></td>
<td><%=worker.getEname()%></td>
<td><%=worker.getJob()%></td>
<td><%=worker.getHiredate()%></td>
<td><%=worker.getSal()%></td>
</tr>
<%
}
%>
</table>
</center>
</body>
</html>
添加功能也可以自行测试
work_add.jsp
<%--
Created by IntelliJ IDEA.
User: l1957
Date: 2021/1/20
Time: 11:30
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=GBK" language="java" pageEncoding="GBK" %>
<html>
<head>
<title>work add</title>
</head>
<% request.setCharacterEncoding("GBK");%>
<body>
<form action="work_add_do.jsp" method="post">
编 号:<input type="text" name="empno"><br>
姓 名:<input type="text" name="ename"><br>
职 位:<input type="text" name="job"><br>
工作日期:<input type="text" name="hiredate"><br>
工 资:<input type="text" name="sal"><br>
<input type="submit" value="注册">
<input type="reset" value="重置">
</form>
</body>
</html>
work_add_do.jsp
<%--
Created by IntelliJ IDEA.
User: l1957
Date: 2021/1/20
Time: 11:31
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=GBK" language="java" pageEncoding="GBK" %>
<%@ page import="com.lqc.factory.*,com.lqc.vo.*"%>
<%@ page import="java.text.*"%>
<html>
<head>
<title>work add do</title>
</head>
<% request.setCharacterEncoding("GBK");%>
<body>
<%
Worker worker=new Worker();
worker.setEmpno(Integer.parseInt(request.getParameter("empno")));
worker.setEname(request.getParameter("ename"));
worker.setJob(request.getParameter("job"));
worker.setHiredate(new SimpleDateFormat("yyyy-MM-dd").parse(request.getParameter("hiredate")));
worker.setSal(Float.parseFloat(request.getParameter("sal")));
try{
if(DAOFactory.getIWorkerDAOInstance().doCreate(worker)){
%>
<h3>信息添加成功!</h3>
<%
}else{
%>
<h3>信息添加失败</h3>
<% } %>
<%
}catch(Exception e){
e.printStackTrace();
}
%>
</body>
</html>
摘自《java web从入门到项目实践》