【Spring】DAO 和 Repository 的区别
DAO 和 Repository 的区别
- 1.概述
- 2.DAO 模式
- 2.1 User
- 2.2 UserDao
- 2.3 UserDaoImpl
- 3.Repository 模式
- 3.1 UserRepository
- 3.2 UserRepositoryImpl
- 4.具有多个 DAO 的 Repository 模式
- 4.1 Tweet
- 4.2 TweetDao 和 TweetDaoImpl
- 4.3 增强 User 域
- 4.4 UserRepositoryImpl
- 5.比较两种模式
- 6.结论
1.概述
通常,Repository 和 DAO 的实现被认为是可互换的,特别是在 以数据为中心 的应用程序中。这造成了对它们差异的混淆。
在本文中,我们将讨论 DAO 和 Repository 模式之间的差异。

2.DAO 模式
数据访问对象(Data Access Object,DAO)模式是数据持久性的抽象,被认为更接近于底层存储,而底层存储通常以表为中心。因此,在许多情况下,我们的 DAO 与数据库表匹配,允许更直接的方式从存储中 发送/检索 数据,从而隐藏丑陋的查询。
让我们来看看 DAO 模式的简单实现。
2.1 User
首先,让我们创建一个基本的 User 域类。
public class User {private Long id;private String userName;private String firstName;private String email;// getters and setters
}
2.2 UserDao
然后,我们将创建 UserDao 接口,该接口为 User 域提供简单的 CRUD 操作。
public interface UserDao {void create(User user);User read(Long id);void update(User user);void delete(String userName);
}
2.3 UserDaoImpl
最后,我们将创建实现 UserDao 接口的 UserDaoImpl 子类。
public class UserDaoImpl implements UserDao {private final EntityManager entityManager;@Overridepublic void create(User user) {entityManager.persist(user);}@Overridepublic User read(long id) {return entityManager.find(User.class, id);}// ...
}
在这里,为了简单起见,我们使用 JPA EntityManager 接口与底层存储交互,并为用户域提供数据访问机制。
3.Repository 模式
根据 Eric Evans 的《领域驱动设计》:Repository 是一种封装存储、检索和搜索行为的机制,它模拟对象的集合。
同样,根据《企业应用架构模式》,它使用类似于集合的接口访问领域对象,在 领域层 和 数据映射层 之间进行调解。换句话说,Repository 也处理数据并隐藏查询,与 DAO 类似。不过,它位于更高层次,更接近应用程序的业务逻辑。
因此,Repository 可以使用 DAO 从数据库获取数据并填充域对象。或者,它可以准备域对象中的数据,并使用 DAO 将其发送到存储系统以实现持久性。
让我们看看 User 域的 Repository 模式的简单实现。
3.1 UserRepository
首先,让我们创建用户存储库接口。
public interface UserRepository {User get(Long id);void add(User user);void update(User user);void remove(User user);
}
在这里,我们添加了一些常用方法,如 get、add、update 和 remove,以处理对象集合。
3.2 UserRepositoryImpl
然后,我们将创建 UserRepositoryImpl 类,提供 UserRepository 接口的实现。
public class UserRepositoryImpl implements UserRepository {private UserDaoImpl userDaoImpl;@Overridepublic User get(Long id) {User user = userDaoImpl.read(id);return user;}@Overridepublic void add(User user) {userDaoImpl.create(user);}// ...
}
在这里,我们使用 UserDaoImpl 从数据库中 发送/检索 数据。
到目前为止,我们可以说 DAO 和 Repository 的实现看起来非常相似,因为 User 类是一个 Anemic Domain。而且,Repository 只是数据访问层(DAO)的另一层。
🚀 只包含数据,不包含业务逻辑的类,就叫作 贫血模型(Anemic Domain Model)。贫血模型将数据与操作分离,破坏了面向对象的封装特性,是一种典型的面向过程的编程风格。
但是,DAO 似乎是 访问数据 的完美候选者,Repository 是 实现业务用例 的理想方式。
4.具有多个 DAO 的 Repository 模式
为了清楚地理解最后一句话,让我们加强 User 域来处理业务用例。
想象一下,我们想通过聚合一个用户的 Twitter 推文、Facebook 帖子等,为他准备一份社交媒体档案。
4.1 Tweet
首先,我们将创建具有一些保存推文信息的属性的 Tweet 类:
public class Tweet {private String email;private String tweetText; private Date dateCreated;// getters and setters
}
4.2 TweetDao 和 TweetDaoImpl
然后,与 UserDao 类似,我们将创建允许获取推文的 TweetDao 界面:
public interface TweetDao {List<Tweet> fetchTweets(String email);
}
同样,我们将创建 TweetDaoImpl 类,该类提供 fetchTweets 方法的实现:
public class TweetDaoImpl implements TweetDao {@Overridepublic List<Tweet> fetchTweets(String email) {List<Tweet> tweets = new ArrayList<Tweet>();//call Twitter API and prepare Tweet objectreturn tweets;}
}
在这里,我们将调用 Twitter API,使用用户的电子邮件获取其所有推文。
因此,在这种情况下,DAO 提供了一种使用第三方 API 的数据访问机制。
4.3 增强 User 域
最后,让我们创建 User 类的 UserSocialMedia 子类,以保留 Tweet 对象的列表。
public class UserSocialMedia extends User {private List<Tweet> tweets;// getters and setters
}
在这里,我们的 UserSocialMedia 是一个复杂的域,其中包含 User 域的属性。
4.4 UserRepositoryImpl
现在,我们将升级我们的 UserRepositoryImpl 类,以提供 User 域对象以及推文列表。
public class UserRepositoryImpl implements UserRepository {private UserDaoImpl userDaoImpl;private TweetDaoImpl tweetDaoImpl;@Overridepublic User get(Long id) {UserSocialMedia user = (UserSocialMedia) userDaoImpl.read(id);List<Tweet> tweets = tweetDaoImpl.fetchTweets(user.getEmail());user.setTweets(tweets);return user;}
}
在这里,UserRepositoryImpl 使用 UserDaoImpl 提取用户数据,并使用 TweetDaoImpl 提取用户的推文。
然后,它聚合两组信息,并提供 UserSocialMedia 类的域对象,该对象对于我们的业务用例非常方便。因此,存储库依赖于 DAO 来访问来自各种源的数据。
同样,我们可以增强我们的用户域以保留 Facebook 帖子列表。
5.比较两种模式
现在我们已经看到了 DAO 和 Repository 模式的细微差别,让我们总结一下它们的区别:
- DAO 是数据持久性的抽象。但是,Repository 是对象集合的抽象。
- DAO 是一个较 低 级别的概念,更接近 存储系统。但是,Repository 是一个更 高 层次的概念,更接近 域对象。
- DAO 作为 数据映射/访问层 工作,隐藏丑陋的查询。但是,Repository 是 域 和 数据访问层 之间的一层,隐藏了整理数据和准备域对象的复杂性。
- DAO 不能使用 Repository 实现。但是,Repository 可以使用 DAO 来访问底层存储。
而且,如果我们有一个贫血域,Repository 将只是一个 DAO。
此外,Repository 模式鼓励域驱动的设计,也为非技术团队成员提供了对数据结构的轻松理解。
- 职责不同:Repository 负责数据访问的逻辑管理,封装与数据库的交互操作,包括数据的增删改查等。Repository 的设计目标是提供一个统一的接口,将数据访问逻辑与业务逻辑分离,使得业务逻辑更加清晰和可维护。DAO 更关注于数据访问的实现细节,与具体的数据库交互,实现数据的存储和检索等功能。
- 抽象层次不同:Repository 提供一种更加抽象的数据访问方式,将数据访问的逻辑从业务逻辑中分离出来,使得业务逻辑与数据访问无关,降低代码耦合度,提高可维护性和可扩展性。Repository 定义一组通用的接口和方法,供业务模块调用。DAO 更接近于具体的数据访问实现,直接与数据库交互,实现数据的存储和检索等功能。DAO 的设计目标是提供一组具体的数据访问方法,以满足业务模块的具体需求。
6.结论
在本文中,我们探讨了 DAO 和 Repository 模式之间的差异。
首先,我们研究了 DAO 模式的基本实现。然后,我们看到了使用 Repository 模式的类似实现。
最后,我们研究了一个利用多个 DAO 的 Repository,它增强了域解决业务用例的能力。
因此,我们可以得出结论,当应用程序从以数据为中心转向面向业务时,Repository 模式被证明是一种更好的方法。
🚀 译自《DAO vs Repository Patterns》
相关文章:
【Spring】DAO 和 Repository 的区别
DAO 和 Repository 的区别 1.概述2.DAO 模式2.1 User2.2 UserDao2.3 UserDaoImpl 3.Repository 模式3.1 UserRepository3.2 UserRepositoryImpl 4.具有多个 DAO 的 Repository 模式4.1 Tweet4.2 TweetDao 和 TweetDaoImpl4.3 增强 User 域4.4 UserRepositoryImpl 5.比较两种模式…...
高阶面试-秒杀系统的设计
场景 特价商品如茅台,在8月1日22点10分0秒开始秒杀 平台用户量:几千万,预计几十万用户感兴趣 需求 临时性的活动,不要太大技术改动 原则 商品不能超卖下单成功的订单不能丢失服务器和数据库不能崩溃尽量不让机器人抢走商品 …...
四十五、 证券基金业数据出境有无特别规范需要注意?
证券基金业数据合规除应遵守本《实务问答》前述的各项通用规定外,还应注意中国证券监督管理委员会等其他机构发布的相关规范。其中,与数据出境相关的主要包括《证券期货业数据分类分级指引》(JR/T 0158—2018,2018年 9月 27日实施…...
02.Linux下安装FFmpeg
目录 一、下载FFmpeg的编译源码 二、编译源码 三、ffmpeg工具结构解析 1、bin目录 2、include库 3、lib库 四、注意事项 五、可能出现的一些问题 1、某些工具未安装/版本过久 2、缺少pkg-config工具 3、缺少ffmplay FFmpeg 是一个开源的跨平台音视频处理工具集&…...
华为RH2288H V2服务器,远程端口安装Linux操作系统
1、管理口 每台服务器的管理口不一样的,假如我的管理IP地址为:192.168.111.201 使用网线,将管理口和自己电脑连接起来,自己ip地址设置成和管理ip同一网段。 使用 ie 浏览器,如果是Edge,必须在Internet Exp…...
JS在线加密简述
JS在线加密,是指:在线进行JS代码混淆加密。通过混淆、压缩、加密等手段,使得JS源代码难以阅读和理解。从而可以有效防止代码被盗用或抄袭,保护开发者的知识产权和劳动成果。常用的JS在线加密网站有:JShaman、JS-Obfusc…...
理想汽车提出3DRealCar:首个大规模3D真实汽车数据集
理想提出3DRealCar,这是第一个大规模 3D 实车数据集,包含 2500 辆在真实场景中拍摄的汽车。我们希望 3DRealCar 可以成为促进汽车相关任务的宝贵资源。 理想汽车提出3DRealCar:首个大规模3D真实汽车数据集! 我们精心策划的高质量3DRealCar数…...
HTML5文旅文化旅游网站模板源码
文章目录 1.设计来源文旅宣传1.1 登录界面演示1.2 注册界面演示1.3 首页界面演示1.4 文旅之行界面演示1.5 文旅之行文章内容界面演示1.6 关于我们界面演示1.7 文旅博客界面演示1.8 文旅博客文章内容界面演示1.9 联系我们界面演示 2.效果和源码2.1 动态效果2.2 源代码2.3 源码目…...
山东大学多核并行2024年回忆版
2024.6.13回忆版 矩阵向量乘不可整除代码 集合通信与点对点通信的区别 块划分、循环划分、循环块划分(14个向量,4个进程) 按行访问还是按列访问快 SISD系统问题 循环依赖问题 问题:为什么不能对这个循环并行化࿰…...
CentOS 7 上搭建 JavaEE 环境
CentOS 7 上搭建 JavaEE 环境 安装 Java 环境 1)检查系统中是否已安装 Java java -version如果未安装,将返回提示信息。 2)安装 Java 8 sudo yum install java-1.8.0-openjdk3)配置 Java 环境变量,编辑 /etc/prof…...
库与表管理的终极指南
数据库的库和表的管理 库的管理1.库的创建2.数据库的查看和使用3.数据库的修改4.数据库的删除 表的管理1.表的创建2.表的修改3.表的删除4.查看一个表 阅读指南: 本文章是数据库教程系列的一部分,专注于数据库的库和表管理。读者可以根据兴趣选择阅读相关…...
等级保护测评在测评中Linux系统怎么改
在等级保护测评中,针对Linux系统的整改主要是为了提高其安全性,使之符合等级保护的基本要求。 以下是一些常见的整改步骤和建议: 1. 身份鉴别: • 强化密码策略,例如设置复杂的密码规则、密码长度、密码复杂度、密码…...
Python项目开发实战:微信跳一跳辅助工具,案例教程编程实例课程详解
一、项目背景与意义 微信跳一跳是微信推出的一款小游戏,玩家需要控制一个小人从一个平台跳到另一个平台上,每成功跳过一个平台,分数就会增加。然而,随着游戏难度的增加,玩家需要更精准的控制和更快的反应速度,这往往让许多玩家感到力不从心。因此,开发一款微信跳一跳的辅…...
STM32 SWD烧写
最小电路 stm32f103x 内部已经集成了振荡电路,可以省略;rst引脚电路,可以省略,boot0,boot1不需要设置 正常烧录 -------------------------------------------------------------------STM32CubeProgrammer v2.9.0 …...
数据库系统概论(第5版教材)
第一章 绪论 1、数据(Data)是描述事物的符号记录; 2、数据库系统的构成:数据库 、数据库管理系统(及其开发工具) 、应用程序和数据库管理员; 3、数据库是长期存储在计算机内、有组织、可共享的大量数据的集合&…...
算法力扣刷题 二十六【459.重复的子字符串】
前言 字符串篇,继续。 记录 二十六【459.重复的子字符串】 一、题目阅读 给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。 示例 1: 输入: s "abab" 输出: true 解释: 可由子串 "ab" 重复两次构成。示例…...
【Linux】虚拟机安装openEuler 24.03 X86_64 教程
目录 一、概述 1.1 openEuler 覆盖全场景的创新平台 1.2 系统框架 1.3 平台框架 二、安装详细步骤 一、概述 1.1 openEuler 覆盖全场景的创新平台 openEuler 已支持 x86、Arm、SW64、RISC-V、LoongArch 多处理器架构,逐步扩展 PowerPC 等更多芯片架构支持&…...
分布式事务:理论与实践
分布式事务:理论与实践 在现代分布式系统中,分布式事务是一种确保跨多个独立系统的一致性和完整性的方法。本文将介绍分布式事务的基本概念、实现方式、在Java中的具体实现以及在实际应用中的案例。 分布式事务的基本概念 分布式事务涉及多个独立的数…...
5、双足机器人mpc动力学模型
为计算机器人的当前实际状态x,需要建立双足质心动力学模型。 速度模型由控制输入变量推导速度公式: x向速度νx :当前机器人x方向的前进速度,初始值由速度传感器实时测量得到。y向速度νy :机器人y方向的平移速度。z向速度νz :垂直方向的速度,对于双足机器人行走时为0:…...
虚拟机配置与windows之间文件夹共享samba服务:
虚拟机配置与windows之间文件夹共享samba服务: #输入安装命令: 第一步: 下载samba cd /etc/ sudo apt-get install samba第二步: 配置用户 sudo smbpasswd -a 虚拟机用户名第三步: 进入配置文件配置共享文件 sudo vim /etc/samba/smb.conf末尾输入以下内容: [s…...
Android Wi-Fi 连接失败日志分析
1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分: 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析: CTR…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
iview框架主题色的应用
1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题,无需引入,直接可…...
HubSpot推出与ChatGPT的深度集成引发兴奋与担忧
上周三,HubSpot宣布已构建与ChatGPT的深度集成,这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋,但同时也存在一些关于数据安全的担忧。 许多网络声音声称,这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...
DiscuzX3.5发帖json api
参考文章:PHP实现独立Discuz站外发帖(直连操作数据库)_discuz 发帖api-CSDN博客 简单改造了一下,适配我自己的需求 有一个站点存在多个采集站,我想通过主站拿标题,采集站拿内容 使用到的sql如下 CREATE TABLE pre_forum_post_…...
前端开发者常用网站
Can I use网站:一个查询网页技术兼容性的网站 一个查询网页技术兼容性的网站Can I use:Can I use... Support tables for HTML5, CSS3, etc (查询浏览器对HTML5的支持情况) 权威网站:MDN JavaScript权威网站:JavaScript | MDN...
大数据治理的常见方式
大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法,以下是几种常见的治理方式: 1. 数据质量管理 核心方法: 数据校验:建立数据校验规则(格式、范围、一致性等)数据清洗&…...
