一、前言
这个DAO设计模式,其实之前用过好多次了,但某些概念还是有的迷糊,故整理如下
二、DAO设计模式
2.1、DAO设计模式中概念
- DAO 属于 J2EE 数据层的操作 即 在 DAO 中封装了一个表在一个项目中所应该具有的全部操作
- J2EE 的组件层次 : 客户端 》 表示层 》 业务层 》 数据层 (数据库中的表)
- DAO对应J2EE的组件层次的数据层,DAO规定的是一个接口,在这个里面定义整个模块对表的操作 如:
- 增加
- 修改
- 删除
- 按 ID 查询
- 查询全部
- 模糊查询
- 等
2.2、几个名词释义
1.O/R Mapping :即Object Relational Mapping(对象关系映射)的缩写。
解释:对象与关系数据库绑定,用对象来表示关系据。
2.VO: 即 值对象(Value Object)
解释:确切的来说VO是业务对象,如果说业务逻辑处理类是它工作的地方,那么实体类则是它的家。
3.PO: 即 持久对象(Persisent Object)
解释:向数据库中添加新数据时创建,删除数据库中数据时削除的。它只能存活在一个数据库连接中,断开连接即被销毁。
4.POJO: 即 简单java对象(plain ordinary java object )
解释:在Object/RelationMapping(对象关系型映射)工具中,能够做到维护数据库表记录的持久对象(PO);中间对象,POJO经持久化或就是PO
5.TO: 即 传输对象(Transfer Object)
解释:在项目的不同层之间传输的对象
6.DAO 即 数据访问对象(data access object)
解释:一个接口,定义对表中数据的操作方式
7.DTO: 即:数据传输对象(Data Transfer Object)
8.BO: 即 业务对象(business object)
2.3、举例
比如说用户登录在登录之前必须要注册,这样才可以实现登录
- 插入 》针对对象的插入
- 对象 》VO,TO,POJO(值对象,传输对象,简单java对象(最根本的Java对象)) 即:只包含属性和setter、getter的方法类
- 客户 》 VO 》DAO VO的对象与表中字段对应
- 定义接口后,要定义实现该接口的实现类,实现类要实现接口中对数据库的所有操作
- 定义一个数据库连接类工具类,由数据库连接类工具类,统一管理数据库连接
- 查询全部的操作返回值是 List,所以需要使用 Iterator 进行输出
- 使用 DAO 之后,前台调用代码减少很多,但可以发现类增加了
- 可以发现以下的一个重要问题:
- PersonDAO dao = new PersonDAOImpl() ;接口直接通过其子类实例化,直接的影响就是程序在调用时必须知道具体的子类,这样会造成修改不方便 所以,必须使用工厂设计,使前台不关注于具体子类是谁
- DAO 整体设计,是采用以下模式:
- 调用处 》 DAO 工厂 》 具体子类实现 》 完成数据库操作
- |-----------------|------------- VO ----------|
- 直接的好处:前台显示与后台逻辑操作分离
三、案例巩固
3.1、实体类 VO对象
package cn.itcase.vo;
public class Admin {
private String id ;
private String name ;
private String password ;
private int age ;
private String email ;
// // VO值对象 包括get和set方法
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
3.2 接口的定义
package cn.itcase.dao;
import java.util.List;
import cn.itcase.vo.Admin;
//规定出了操作admin表在此项目里的全部方法
public interface AdminDao {
// 增加操作
public void insert(Admin aadmin) throws Exception;
// 修改操作
public void update(Admin aadmin) throws Exception;
// 删除操作
public void delete(String id) throws Exception;
// 按ID查询操作
public Admin queryById(String id) throws Exception;
// 查询全部
public List<Admin> queryAll() throws Exception;
// 模糊查询
public List<Admin> queryByLike(String cond) throws Exception;
}
3.3、接口实现类的定义
package cn.itcase.dao.impl;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import cn.itcase.dao.AdminDao;
import cn.itcase.jdbcutils.JdbcUtils;
import cn.itcase.vo.Admin;
public class AdminDaoImpl implements AdminDao {
// 全局变量初始化
PreparedStatement pstmt = null; // 预编译对象
Connection conn = null; // 连接对象
ResultSet rs = null; // 结果集对象
// 增加操作
@Override
public void insert(Admin admin) throws Exception {
try {
// 0.需要操作的sql
String sql = "insert into admin(id,name,password,age,email) values(?,?,?,?,?);";
// 1.使用工具类连接数据库
conn = JdbcUtils.getConnection();
// 2.预编译sql
pstmt = conn.prepareStatement(sql);
// 3.设置参数
pstmt.setString(1, admin.getId());
pstmt.setString(2, admin.getName());
pstmt.setString(3, admin.getPassword());
pstmt.setInt(4, admin.getAge());
pstmt.setString(5, admin.getEmail());
// 4.执行相应操作并返回结果
int result = pstmt.executeUpdate();
System.out.println("影响了:" + result + "记录");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
JdbcUtils.closeAll(conn, pstmt, null); // 关闭对象
}
}
// 修改操作
@Override
public void update(Admin admin) throws Exception {
try {
// 0.需要操作的sql
String sql = "UPDATE admin SET name=?,password=?,age=?,email=? WHERE id=?";
// 1.使用工具类连接数据库
conn = JdbcUtils.getConnection();
// 2.预编译sql
pstmt = conn.prepareStatement(sql);
// 3.设置参数
pstmt.setString(1, admin.getName());
pstmt.setString(2, admin.getPassword());
pstmt.setInt(3, admin.getAge());
pstmt.setString(4, admin.getEmail());
pstmt.setString(5, admin.getId());
// 4.执行相应操作并返回结果
int result = pstmt.executeUpdate();
System.out.println("影响了" + result + "记录");
} catch (Exception e) {
throw new RuntimeException(e);
// 5.关闭数据库连接对象
} finally {
JdbcUtils.closeAll(conn, pstmt, null); // 关闭对象
}
}
// 删除操作
@Override
public void delete(String id) throws Exception {
try {
// 0.需要执行的sql语句
String sql = "DELETE FROM admin WHERE id=?";
// 1.使用工具类连接数据库
conn = JdbcUtils.getConnection();
// 2.预编译sql
pstmt = conn.prepareStatement(sql);
// 3.设置参数
pstmt.setString(1, id);
// 4.执行相应操作并返回结果
int result = pstmt.executeUpdate();
System.out.println("影响了" + result + "记录");
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// 5.关闭数据库连接对象
JdbcUtils.closeAll(conn, pstmt, null);
}
}
// 按ID查询操作
@Override
public Admin queryById(String id) throws Exception {
Admin admin = null;
try {
// 0.需要执行的sql操作
String sql = "SELECT id,name,password,age,email FROM admin WHERE id=?";
// 1.使用工具类连接数据库
conn = JdbcUtils.getConnection();
// 2.预编译sql
pstmt = conn.prepareStatement(sql);
// 3.设置参数
pstmt.setString(1, id);
// 4.执行相应操作并返回结果
rs = pstmt.executeQuery();
System.out.println(rs);
// 创建list 并遍历list
// List<Admin> list = new ArrayList<Admin>();
if (rs.next()) {
// 查询出内容,之后将查询出的内容赋值给admin对象
admin = new Admin();
admin.setId(rs.getString(1));
admin.setName(rs.getString(2));
admin.setPassword(rs.getString(3));
admin.setAge(rs.getInt(4));
admin.setEmail(rs.getString(5));
// list.add(admin);
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// 5.关闭数据库连接对象
JdbcUtils.closeAll(conn, pstmt, rs);
}
return admin;
}
// 查询全部
@Override
public List<Admin> queryAll() throws Exception {
try {
// 0.需要执行的sql操作
String sql = "SELECT id,name,password,age,email FROM admin";
// 1.使用工具类连接数据库
conn = JdbcUtils.getConnection();
// 2.预编译sql
pstmt = conn.prepareStatement(sql);
// 3.设置参数
// 3.1 创建list
List<Admin> list = new ArrayList<Admin>();
// 3.2 遍历list
while (rs.next()) {
Admin admin = null;
admin = new Admin();
admin.setId(rs.getString(1));
admin.setName(rs.getString(2));
admin.setPassword(rs.getString(3));
admin.setAge(rs.getInt(4));
admin.setEmail(rs.getString(5));
list.add(admin);
}
// 4.执行相应操作并返回结果
rs = pstmt.executeQuery();
System.out.println("打印影响的记录" + rs);
return list;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// 5.关闭数据库连接对象
JdbcUtils.closeAll(conn, pstmt, rs);
}
}
// 模糊查询
@Override
public List<Admin> queryByLike(String cond) throws Exception {
try {
// 0.需要执行的sql操作
String sql = "SELECT id,name,password,age,email FROM admin WHERE name LIKE ? or email LIKE ?";
// 1.使用工具类连接数据库
conn = JdbcUtils.getConnection();
// 2.预编译sql
pstmt = conn.prepareStatement(sql);
// 3. 执行预编译
rs = pstmt.executeQuery();
// 4.设置参数
//4.1 模糊查询条件设置
pstmt.setString(1,"%"+cond+"%") ;
pstmt.setString(2,"%"+cond+"%") ;
// 4.2 创建list
List<Admin> list = new ArrayList<Admin>();
// 4.3 遍历list
while(rs.next()){
Admin admin = new Admin();
admin = new Admin();
admin.setId(rs.getString(1));
admin.setName(rs.getString(2));
admin.setPassword(rs.getString(3));
admin.setAge(rs.getInt(4));
admin.setEmail(rs.getString(5));
list.add(admin);
}
return list;
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
// 5.关闭数据库连接对象
JdbcUtils.closeAll(conn, pstmt, rs);
}
}
}
3.4、DAO工厂
package cn.itcase.daofactory;
import cn.itcase.dao.AdminDao;
import cn.itcase.dao.impl.AdminDaoImpl;
public class DaoFactory {
public static AdminDao getAdminDaoInstance() {
return new AdminDaoImpl();
}
}
3.5、JDBC连接数据的工具类
package cn.itcase.jdbcutils;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class JdbcUtils {
// 连接参数
// private String url = "jdbc:mysql://localhost:3306/jdbc_demo";
private static String url = "jdbc:mysql://admin?characterEncoding=utf8";
private static String user = "root";
private static String password = "0000";
/*
* 返回连接对象
*/
public static Connection getConnection() {
try {
Class.forName("com.mysql,jdbc.Driver");
return DriverManager.getConnection(url, user, password);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/* 关闭 */
public static void closeAll(Connection conn, PreparedStatement pstmt,
ResultSet rs) {
try {
if (rs != null) {
rs.close(); // 快速异常捕获 Alt + shift + z
rs = null; // 建议垃圾回收期回收资源
}
if (pstmt != null) {
pstmt.close();
pstmt = null;
}
if (conn != null && !conn.isClosed()) {
conn.close();
conn = null;
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
}
3.6、数据代码
/*建库*/
/*建库并设置默认编码*/
GBK: create database admin DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;
/*本项目使用utf8的默认编码*/
UTF8: CREATE DATABASE admin DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
/*使用库*/
USE admin
/*建表*/
CREATE TABLE admin
(
id VARCHAR(32) NOT NULL PRIMARY KEY ,
NAME VARCHAR(20) NOT NULL ,
PASSWORD VARCHAR(20) NOT NULL ,
age VARCHAR(20) NOT NULL ,
email VARCHAR(20) NOT NULL
) ;
三、总结
DAO设计模式基本上就是这么个固定的套路,接口实现类中的五个步骤有点瑕疵。但不影响总体上对于设计DAO设计模式的理解。值得注意的是DAO这工厂类,DAO工厂类的主要优点是实现接口与具体实现的分离,可以使系统能够面向接口编程,而不是依赖于很多具体的类。也就是说通过工厂类这个中间对象来管理实现类,而不使接口实现类依赖接口