J2EE模式---数据访问对象模式

数据访问对象模式基础概念

数据访问对象模式(Data Access Object Pattern,简称 DAO 模式)是一种结构型设计模式,其核心思想是将数据访问逻辑与业务逻辑分离,通过一个抽象层(DAO)来处理数据的持久化和检索操作,使业务层无需关心数据存储的细节(如数据库类型、连接管理等)。这种模式提高了代码的可维护性和可测试性,尤其适用于企业级应用中数据访问层的设计。

数据访问对象模式的核心组件

  1. 数据访问对象接口(DAO Interface)

    • 定义数据访问操作的抽象方法(如 CRUD 操作)
    • 为不同的数据访问实现提供统一的接口
  2. 数据访问对象实现(DAO Implementation)

    • 实现 DAO 接口,处理具体的数据访问逻辑
    • 包含与数据库或其他数据源的交互代码
  3. 模型对象 / 值对象(Model/Value Object)

    • 表示业务数据的实体类
    • 通常是简单的 POJO(Plain Old Java Objects),包含属性和 getter/setter 方法
  4. 工厂类(Factory Class)

    • 负责创建 DAO 实例的工厂
    • 隐藏 DAO 实现的创建细节,提供统一的获取方式

数据访问对象模式的工作流程

  1. 业务层调用:业务层通过 DAO 接口调用数据访问方法
  2. DAO 实现处理:具体的 DAO 实现类处理数据访问请求
  3. 数据源交互:DAO 实现与数据源(如数据库、文件系统)交互
  4. 数据转换:将数据源中的数据转换为模型对象,或反之
  5. 结果返回:将处理结果返回给业务层

数据访问对象模式的实现

下面通过一个简单的 Java 示例展示数据访问对象模式的实现:

// 1. 模型对象 - 用户
class User {private int id;private String name;private String email;public User(int id, String name, String email) {this.id = id;this.name = name;this.email = email;}// Getters and setterspublic int getId() { return id; }public void setId(int id) { this.id = id; }public String getName() { return name; }public void setName(String name) { this.name = name; }public String getEmail() { return email; }public void setEmail(String email) { this.email = email; }
}// 2. DAO接口
interface UserDAO {List<User> getAllUsers();User getUserById(int id);void saveUser(User user);void deleteUser(User user);
}// 3. DAO实现 - 使用JDBC访问数据库
class UserDAOImpl implements UserDAO {private static final String DB_URL = "jdbc:mysql://localhost:3306/mydb";private static final String DB_USER = "root";private static final String DB_PASSWORD = "password";@Overridepublic List<User> getAllUsers() {List<User> users = new ArrayList<>();String sql = "SELECT * FROM users";try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(sql)) {while (rs.next()) {int id = rs.getInt("id");String name = rs.getString("name");String email = rs.getString("email");users.add(new User(id, name, email));}} catch (SQLException e) {e.printStackTrace();}return users;}@Overridepublic User getUserById(int id) {String sql = "SELECT * FROM users WHERE id = ?";User user = null;try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);PreparedStatement pstmt = conn.prepareStatement(sql)) {pstmt.setInt(1, id);try (ResultSet rs = pstmt.executeQuery()) {if (rs.next()) {String name = rs.getString("name");String email = rs.getString("email");user = new User(id, name, email);}}} catch (SQLException e) {e.printStackTrace();}return user;}@Overridepublic void saveUser(User user) {String sql = "INSERT INTO users (id, name, email) VALUES (?, ?, ?)";try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);PreparedStatement pstmt = conn.prepareStatement(sql)) {pstmt.setInt(1, user.getId());pstmt.setString(2, user.getName());pstmt.setString(3, user.getEmail());pstmt.executeUpdate();} catch (SQLException e) {e.printStackTrace();}}@Overridepublic void deleteUser(User user) {String sql = "DELETE FROM users WHERE id = ?";try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);PreparedStatement pstmt = conn.prepareStatement(sql)) {pstmt.setInt(1, user.getId());pstmt.executeUpdate();} catch (SQLException e) {e.printStackTrace();}}
}// 4. DAO工厂
class DAOFactory {public static UserDAO getUserDAO() {return new UserDAOImpl();}
}// 5. 客户端代码
public class DAOPatternDemo {public static void main(String[] args) {// 获取DAO实例UserDAO userDAO = DAOFactory.getUserDAO();// 创建用户User newUser = new User(1, "John Doe", "john@example.com");userDAO.saveUser(newUser);// 获取所有用户List<User> users = userDAO.getAllUsers();System.out.println("所有用户:");for (User user : users) {System.out.println("ID: " + user.getId() + ", 姓名: " + user.getName() + ", 邮箱: " + user.getEmail());}// 根据ID获取用户User user = userDAO.getUserById(1);System.out.println("\nID为1的用户: " + user.getName());// 删除用户userDAO.deleteUser(user);System.out.println("\n删除用户后,所有用户:");users = userDAO.getAllUsers();for (User u : users) {System.out.println("ID: " + u.getId() + ", 姓名: " + u.getName());}}
}

数据访问对象模式的应用场景

  1. 企业级应用 - 如 ERP、CRM 系统中,分离业务逻辑与数据库访问
  2. 多层架构 - 在 MVC、三层架构中,作为数据访问层的标准实现
  3. 异构数据源 - 访问不同类型的数据源(如关系型数据库、NoSQL 数据库)
  4. 测试场景 - 便于在单元测试中使用模拟 DAO 替代真实数据访问
  5. 数据缓存 - 在 DAO 层实现缓存机制,提高数据访问性能
  6. ORM 框架 - 如 Hibernate、MyBatis 等框架的设计基础

数据访问对象模式的优缺点

优点

  1. 分离关注点 - 业务逻辑与数据访问逻辑分离,提高代码可维护性
  2. 降低耦合度 - 业务层与数据访问层松耦合,便于独立修改和测试
  3. 提高可测试性 - 可通过模拟 DAO 实现简化单元测试
  4. 支持多数据源 - 可轻松切换不同的数据源实现(如从 MySQL 到 Oracle)
  5. 集中管理 - 数据访问逻辑集中在 DAO 中,便于统一优化和维护
  6. 符合开闭原则 - 可在不修改业务层的情况下扩展或修改 DAO 实现

缺点

  1. 代码冗余 - 每个实体类都需要对应的 DAO 接口和实现,可能导致代码量增加
  2. 学习曲线 - 对于简单应用,引入 DAO 模式可能增加复杂度
  3. 性能开销 - 多层抽象可能引入额外的性能开销
  4. 维护挑战 - 如果 DAO 实现不当,可能导致大量重复代码或难以维护的逻辑
  5. 事务管理复杂 - 在跨多个 DAO 的事务中,管理一致性可能变得复杂

使用数据访问对象模式的最佳实践

  1. 接口设计 - DAO 接口应基于业务需求而非底层数据源
  2. 异常处理 - DAO 应处理数据访问异常,向上层抛出业务异常
  3. 资源管理 - 确保数据库连接等资源被正确关闭(如使用 try-with-resources)
  4. 批处理支持 - 为批量操作提供专门的方法,提高性能
  5. 缓存机制 - 在 DAO 层实现适当的缓存策略,减少数据库访问
  6. 事务管理 - 结合使用事务管理器确保数据一致性
  7. 日志记录 - 在 DAO 中添加必要的日志记录,便于调试和监控
  8. 使用 ORM 框架 - 对于复杂应用,考虑使用 Hibernate、MyBatis 等 ORM 框架简化 DAO 实现

总结

数据访问对象模式通过抽象数据访问逻辑,实现了业务层与数据持久层的解耦,是企业级应用中数据访问层的标准设计模式。它在提高代码可维护性、可测试性和支持多数据源等方面具有显著优势,但需要合理设计以避免过度复杂。在实际开发中,DAO 模式常与其他模式(如工厂模式、单例模式)结合使用,并可借助 ORM 框架进一步简化实现。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/92919.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/92919.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【OpenCV篇】OpenCV——02day.图像预处理(1)

目录 前言 一、图像色彩空间转换 1 RGB颜色空间 2 颜色加法 3 颜色加权加法 4 HSV颜色空间 5 RGB转Gray(灰度) 二、灰度实验 1 灰度图 2 最大值法 3 平均值法 4 加权均值法 5 两个极端的灰度值 三、图像二值化处理 二值图像 1 阈值法(THRESH_BINARY) 2 反阈值…

经典IDE之Turbo C

写的程序不多&#xff0c;换过的 IDE 不少&#xff0c;本文将列举曾经用过的不同 C 语言相关的 IDE 环境&#xff0c;既是纪念&#xff0c;也是回忆。值得注意的是 IDE 的出现是为了提高开发效率&#xff0c;有一个相对成熟的编译环境和程序。从编程的角度来看&#xff0c;过分…

Go 多模块仓库标签管理教程

为了方便自己开发&#xff0c;自己写了个小工具&#xff1a;DzhGO 代码生成工具 功能特点标题 初始化项目基础结构生成插件模块代码生成模型和实体代码生成服务接口和实现代码支持 admin 和 app 两种模块类型生成项目基础目录 具体介绍看仓库&#xff1a; https://github.co…

IDEA 类上方注释 签名

File -->settings–>Editor–>File and Code Templates–>class新建 Class 类上方添加内容&#xff1a;/*** author Jagger* since ${DATE} ${TIME}*/

卫星通信终端天线对星之:参考星对星

我们在前面的文章中介绍了3种卫星通信终端的对星模式&#xff0c;分别是&#xff1a; 卫星通信终端天线的5种对星模式之一&#xff1a;信标跟踪 卫星通信终端天线的5种对星模式之二&#xff1a;功率检测型载波跟踪 卫星通信终端天线的5种对星模式之二&#xff1a;DVB跟踪 今…

来自麻省理工和AI制药公司 Recursion 的结构与结合亲和力预测模型Boltz-2,解决小分子药物发现的关键问题

1. Boltz-2介绍 文章来源&#xff1a;http://jeremywohlwend.com/assets/boltz2.pdf 开源代码来源&#xff1a;https://github.com/jwohlwend/boltz 该AI模型由麻省理工学院计算机科学与人工智能实验室与上市AI制药公司Recursion一起开发&#xff0c;双方在Boltz-1的基础之上…

从零用java实现 小红书 springboot vue uniapp(14) 集成阿里云短信验证码

从零用java实现 小红书 springboot vue uniapp&#xff08;14&#xff09; 集成阿里云短信验证码 移动端演示 http://8.146.211.120:8081/#/ 管理端演示 http://8.146.211.120:8088/#/ 项目整体介绍及演示 前言 在现代应用中&#xff0c;手机号不仅是用户的唯一标识&#xff0…

`<< EOF` 与 `<< ‘EOF‘` 与 `<< “EOF“`有无引号的区别多回答笔记250722

<< EOF 与 << EOF 与 << "EOF"有无引号的区别多回答笔记250722 实测 自测代码: # 定义变量 hello"ni hao"# 无引号 tee << EOF # 无引号 ${hello} world \n $(date) # 无引号 EOF# 单引号 tee << EOF # 单…

点击按钮滚动到底功能vue的v-on:scroll运用

使用vue自带的监听滚动功能v-on:scroll&#xff0c;滚动条变化时&#xff0c;会调用方法 checkScrollStatus&#xff0c;如果滚动条在容器底部时&#xff0c;则隐藏按钮&#xff0c;否则显示按钮&#xff0c;点击按钮能一键滚动到底部。<div class"chat-area" ref…

Linux下编译SLEPc

本文记录在Linux下编译安装SLEPc的流程。 一、下载代码 git clone https://github.com/slepc/slepc.git cd ./slepc二、安装依赖 2.1 安装PETSc 参见: <Linux下编译安装PETSc> 2.2 安装intel oneAPI sudo apt install intel-oneapi-base-toolkit sudo apt install i…

【无标题】qwen3-8b 强化学习训练后的模型,可以接着 进行其他grpo 强化学习训练 吗

ser_count’, 0),)} {((‘valid_user_count’, 1),)} 44 0.0 88 [0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6, 0.0, 0.6, 0.0, 0.6, 0.0, 0.6] 55 100%|???{‘loss’: 0.0132, ‘grad_norm’: 0.07552657276391983, ‘learning_rate’: 2e-06, ‘num_tokens’: 2098…

IDC权威认可:瑞数信息双项入选《中国大模型安全保护市场概览》

近日&#xff0c;国际数据公司IDC正式发布了《中国大模型安全保护市场概览&#xff0c;2025&#xff1a;全方位安全检测与防护构建可信AI》报告。本次报告中IDC结合全球统一定义以及中国市场特色&#xff0c;将中国大模型安全保护市场划分为7个细分领域&#xff0c;并通过对中国…

多智能体(Multi-agent)策略模式:思维链CoT和ReAct

参考&#xff1a;https://zhuanlan.zhihu.com/p/704523060 &#x1f3af; 一句话记住 CoT&#xff1a;像“考试时在草稿纸上写完所有步骤&#xff0c;再抄答案”。ReAct&#xff1a;像“玩密室逃脱&#xff0c;每开一个箱子就去找下一个线索”。 用小学生能听懂的话 两个小故事…

ChatGPT指令大全:输入需求=输出完整方案

ChatGPT指令大全提供数百个精炼过的指令语句 (提示词)&#xff0c;让你充分发挥 ChatGPT 的强大功能 一、核心功能模块分类 1. 求职与面试 简历优化 专业反馈&#xff1a;按面试官视角分析简历并提出改进建议量化数据&#xff1a;为经历添加具体数字&#xff08;如提升效率30…

Java零基础入门学习知识点2-JDK安装配置+Maven

文章目录版本提示参考视频Maven环境准备一、安装Java开发工具包&#xff08;JDK&#xff09;二、JDK环境配置三、下载Maven安装包*四、Maven环境配置&#xff08;可省略&#xff09;*五、验证安装&#xff08;上一步没做&#xff0c;这步无法验证&#xff0c;可省&#xff09;六…

基于单片机智能衣柜/智能衣橱设计

传送门 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目速选一览表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品题目功能速览 概述 本设计实现了一种基于单片机的多功能智能衣柜&#xff0c;融合环境检测、安全防护与用户交互功能…

自动语音识别(ASR)技术详解

语音识别&#xff08;Automatic Speech Recognition, ASR&#xff09;是人工智能和自然语言处理领域的重要技术&#xff0c;旨在将人类的语音信号转换为对应的文本。近年来&#xff0c;深度学习的突破推动语音识别系统从实验室走入日常生活&#xff0c;为智能助手、实时翻译、医…

【MySQL】MySQL 事务和锁详解

一、MySQL 事务 1.1 事务介绍 在 MySQL 中&#xff0c;事务&#xff08;Transaction&#xff09; 是一组不可分割的 SQL 操作序列&#xff0c;这些操作要么全部成功执行&#xff0c;要么全部失败回滚&#xff0c;以此保证数据库操作的完整性和一致性。 事务将数据库从一种一致…

虚拟直线阈值告警人员计数算法暑期应用

智慧人员计数助力暑期&#xff1a;技术赋能安全管理的创新实践一、背景&#xff1a;暑期人流激增下的安全管理挑战暑期是旅游、商业、交通等场景的客流高峰期&#xff0c;人员密集区域易引发踩踏事故、管理混乱等安全隐患。传统人工计数方式效率低、误差大&#xff0c;难以满足…

SQL164 2021年11月每天新用户的次日留存率

SQL164 2021年11月每天新用户的次日留存率 思路 ​找出新用户​&#xff1a;确定每个用户首次活跃的日期&#xff08;即新用户&#xff09; 例如101用户在11月1日首次出现 ​处理跨天活跃​&#xff1a;考虑用户可能跨天活跃的情况&#xff08;in_time和out_time不在同一天&a…