当前位置: 首页 > news >正文

【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 ObjectDAO)模式是数据持久性的抽象,被认为更接近于底层存储,而底层存储通常以表为中心。因此,在许多情况下,我们的 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);
}

在这里,我们添加了一些常用方法,如 getaddupdateremove,以处理对象集合。

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.比较两种模式…...

高阶面试-秒杀系统的设计

场景 特价商品如茅台&#xff0c;在8月1日22点10分0秒开始秒杀 平台用户量&#xff1a;几千万&#xff0c;预计几十万用户感兴趣 需求 临时性的活动&#xff0c;不要太大技术改动 原则 商品不能超卖下单成功的订单不能丢失服务器和数据库不能崩溃尽量不让机器人抢走商品 …...

四十五、 证券基金业数据出境有无特别规范需要注意?

证券基金业数据合规除应遵守本《实务问答》前述的各项通用规定外&#xff0c;还应注意中国证券监督管理委员会等其他机构发布的相关规范。其中&#xff0c;与数据出境相关的主要包括《证券期货业数据分类分级指引》&#xff08;JR/T 0158—2018&#xff0c;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、管理口 每台服务器的管理口不一样的&#xff0c;假如我的管理IP地址为&#xff1a;192.168.111.201 使用网线&#xff0c;将管理口和自己电脑连接起来&#xff0c;自己ip地址设置成和管理ip同一网段。 使用 ie 浏览器&#xff0c;如果是Edge&#xff0c;必须在Internet Exp…...

JS在线加密简述

JS在线加密&#xff0c;是指&#xff1a;在线进行JS代码混淆加密。通过混淆、压缩、加密等手段&#xff0c;使得JS源代码难以阅读和理解。从而可以有效防止代码被盗用或抄袭&#xff0c;保护开发者的知识产权和劳动成果。常用的JS在线加密网站有&#xff1a;JShaman、JS-Obfusc…...

理想汽车提出3DRealCar:首个大规模3D真实汽车数据集

理想提出3DRealCar&#xff0c;这是第一个大规模 3D 实车数据集&#xff0c;包含 2500 辆在真实场景中拍摄的汽车。我们希望 3DRealCar 可以成为促进汽车相关任务的宝贵资源。 理想汽车提出3DRealCar&#xff1a;首个大规模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回忆版 矩阵向量乘不可整除代码 集合通信与点对点通信的区别 块划分、循环划分、循环块划分&#xff08;14个向量&#xff0c;4个进程&#xff09; 按行访问还是按列访问快 SISD系统问题 循环依赖问题 问题&#xff1a;为什么不能对这个循环并行化&#xff0…...

CentOS 7 上搭建 JavaEE 环境

CentOS 7 上搭建 JavaEE 环境 安装 Java 环境 1&#xff09;检查系统中是否已安装 Java java -version如果未安装&#xff0c;将返回提示信息。 2&#xff09;安装 Java 8 sudo yum install java-1.8.0-openjdk3&#xff09;配置 Java 环境变量&#xff0c;编辑 /etc/prof…...

库与表管理的终极指南

数据库的库和表的管理 库的管理1.库的创建2.数据库的查看和使用3.数据库的修改4.数据库的删除 表的管理1.表的创建2.表的修改3.表的删除4.查看一个表 阅读指南&#xff1a; 本文章是数据库教程系列的一部分&#xff0c;专注于数据库的库和表管理。读者可以根据兴趣选择阅读相关…...

等级保护测评在测评中Linux系统怎么改

在等级保护测评中&#xff0c;针对Linux系统的整改主要是为了提高其安全性&#xff0c;使之符合等级保护的基本要求。 以下是一些常见的整改步骤和建议&#xff1a; 1. 身份鉴别&#xff1a; • 强化密码策略&#xff0c;例如设置复杂的密码规则、密码长度、密码复杂度、密码…...

Python项目开发实战:微信跳一跳辅助工具,案例教程编程实例课程详解

一、项目背景与意义 微信跳一跳是微信推出的一款小游戏,玩家需要控制一个小人从一个平台跳到另一个平台上,每成功跳过一个平台,分数就会增加。然而,随着游戏难度的增加,玩家需要更精准的控制和更快的反应速度,这往往让许多玩家感到力不从心。因此,开发一款微信跳一跳的辅…...

STM32 SWD烧写

最小电路 stm32f103x 内部已经集成了振荡电路&#xff0c;可以省略&#xff1b;rst引脚电路&#xff0c;可以省略&#xff0c;boot0,boot1不需要设置 正常烧录 -------------------------------------------------------------------STM32CubeProgrammer v2.9.0 …...

数据库系统概论(第5版教材)

第一章 绪论 1、数据(Data)是描述事物的符号记录&#xff1b; 2、数据库系统的构成&#xff1a;数据库 、数据库管理系统&#xff08;及其开发工具&#xff09; 、应用程序和数据库管理员&#xff1b; 3、数据库是长期存储在计算机内、有组织、可共享的大量数据的集合&…...

算法力扣刷题 二十六【459.重复的子字符串】

前言 字符串篇&#xff0c;继续。 记录 二十六【459.重复的子字符串】 一、题目阅读 给定一个非空的字符串 s &#xff0c;检查是否可以通过由它的一个子串重复多次构成。 示例 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 多处理器架构&#xff0c;逐步扩展 PowerPC 等更多芯片架构支持&…...

分布式事务:理论与实践

分布式事务&#xff1a;理论与实践 在现代分布式系统中&#xff0c;分布式事务是一种确保跨多个独立系统的一致性和完整性的方法。本文将介绍分布式事务的基本概念、实现方式、在Java中的具体实现以及在实际应用中的案例。 分布式事务的基本概念 分布式事务涉及多个独立的数…...

5、双足机器人mpc动力学模型

为计算机器人的当前实际状态x,需要建立双足质心动力学模型。 速度模型由控制输入变量推导速度公式: x向速度νx :当前机器人x方向的前进速度,初始值由速度传感器实时测量得到。y向速度νy :机器人y方向的平移速度。z向速度νz :垂直方向的速度,对于双足机器人行走时为0:…...

虚拟机配置与windows之间文件夹共享samba服务:

虚拟机配置与windows之间文件夹共享samba服务: #输入安装命令&#xff1a; 第一步: 下载samba cd /etc/ sudo apt-get install samba第二步: 配置用户 sudo smbpasswd -a 虚拟机用户名第三步: 进入配置文件配置共享文件 sudo vim /etc/samba/smb.conf末尾输入以下内容: [s…...

【网络】每天掌握一个Linux命令 - iftop

在Linux系统中&#xff0c;iftop是网络管理的得力助手&#xff0c;能实时监控网络流量、连接情况等&#xff0c;帮助排查网络异常。接下来从多方面详细介绍它。 目录 【网络】每天掌握一个Linux命令 - iftop工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

云原生安全实战:API网关Kong的鉴权与限流详解

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关&#xff08;API Gateway&#xff09; API网关是微服务架构中的核心组件&#xff0c;负责统一管理所有API的流量入口。它像一座…...

十九、【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建

【用户管理与权限 - 篇一】后端基础:用户列表与角色模型的初步构建 前言准备工作第一部分:回顾 Django 内置的 `User` 模型第二部分:设计并创建 `Role` 和 `UserProfile` 模型第三部分:创建 Serializers第四部分:创建 ViewSets第五部分:注册 API 路由第六部分:后端初步测…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)

错误一&#xff1a;yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因&#xff0c;后面把yaml.safe_dump直接替换成yaml.dump&#xff0c;确实能保存&#xff0c;但出现乱码&#xff1a; 放弃yaml.dump&#xff0c;又切…...