• DAO 与存储库Repository模式


    1. 概述

    通常,存储库Repository和DAO的实现被认为是可互换的,特别是在以数据为中心的应用程序中。这造成了对它们差异的混淆。

    在本文中,我们将讨论 DAO 和存储库模式之间的差异。

    2. DAO模式

    数据访问对象模式(也称为 DAO 模式)是数据持久性的抽象,被认为更接近于底层存储,而底层存储通常以表为中心

    因此,在许多情况下,我们的DAO与数据库表匹配,允许更直接的方式从存储中发送/检索数据,从而隐藏丑陋的查询。

    让我们来看看 DAO 模式的简单实现。

    2.1. User

    首先,让我们创建一个基本User域类:

    1. public class User {
    2. private Long id;
    3. private String userName;
    4. private String firstName;
    5. private String email;
    6. // getters and setters
    7. }

    2.2. UserDao

    然后,我们将创建UserDao接口,该接口为User域提供简单的 CRUD 操作:

    1. public interface UserDao {
    2. void create(User user);
    3. User read(Long id);
    4. void update(User user);
    5. void delete(String userName);
    6. }

    2.3. UserDaoImpl

    最后,我们将创建实现UserDao接口的UserDaoImpl子类:

    1. public class UserDaoImpl implements UserDao {
    2. private final EntityManager entityManager;
    3. @Override
    4. public void create(User user) {
    5. entityManager.persist(user);
    6. }
    7. @Override
    8. public User read(long id) {
    9. return entityManager.find(User.class, id);
    10. }
    11. // ...
    12. }

    在这里,为简单起见,我们使用 JPA 实体管理器接口与底层存储进行交互,并为User域提供数据访问机制。

    3. 存储库模式

    根据 Eric Evans 的著作《域驱动设计》,“存储库是一种封装存储、检索和搜索行为的机制,它模拟对象的集合。

    同样,根据企业应用程序体系结构的模式,它“使用类似集合的接口在域和数据映射层之间进行调解,以访问域对象。

    换句话说,存储库还处理数据并隐藏类似于DAO的查询。但是,它位于更高的级别,更接近于应用的业务逻辑。

    因此,存储库可以使用 DAO 从数据库获取数据并填充域对象。或者,它可以准备域对象中的数据,并使用 DAO 将其发送到存储系统以实现持久性。

    让我们检查一下 User 域的存储库模式的简单实现。

    3.1. UserRepository

    首先,让我们创建用户存储库接口:

    1. public interface UserRepository {
    2. User get(Long id);
    3. void add(User user);
    4. void update(User user);
    5. void remove(User user);
    6. }

    在这里,我们添加了一些常用方法,如获取添加更新删除,以处理对象集合。

    3.2. UserRepositoryImpl

    然后,我们将创建UserRepositoryImpl类,提供UserRepository接口的实现:

    1. public class UserRepositoryImpl implements UserRepository {
    2. private UserDaoImpl userDaoImpl;
    3. @Override
    4. public User get(Long id) {
    5. User user = userDaoImpl.read(id);
    6. return user;
    7. }
    8. @Override
    9. public void add(User user) {
    10. userDaoImpl.create(user);
    11. }
    12. // ...
    13. }

    在这里,我们使用UserDaoImpl 数据库中发送/检索数据。

    到目前为止,我们可以说DAO和存储库的实现看起来非常相似,因为User类是一个贫乏的领域。而且,存储库只是数据访问层(DAO)的另一层。

    但是,DAO似乎是访问数据的完美候选者,存储库是实现业务用例的理想方式

    4. 具有多个 DAO 的存储库模式

    为了清楚地理解最后一条语句,让我们增强我们的 User 域来处理业务用例。

    想象一下,我们希望通过聚合用户的Twitter推文,Facebook帖子等来准备用户的社交媒体个人资料。

    4.1. Tweet

    首先,我们将创建具有一些保存推文信息的属性的 Tweet 类:

    1. public class Tweet {
    2. private String email;
    3. private String tweetText;
    4. private Date dateCreated;
    5. // getters and setters
    6. }

    4.2. TweetDao TweetDaoImpl

    然后,与UserDao类似,我们将创建允许获取推文的 TweetDao 界面:

    1. public interface TweetDao {
    2. List fetchTweets(String email);
    3. }

    同样,我们将创建TweetDaoImpl 类,该类提供fetchTweets 方法的实现:

    1. public class TweetDaoImpl implements TweetDao {
    2. @Override
    3. public List fetchTweets(String email) {
    4. List tweets = new ArrayList();
    5. //call Twitter API and prepare Tweet object
    6. return tweets;
    7. }
    8. }

    在这里,我们将调用Twitter API来获取用户使用其电子邮件发送的所有推文。

    因此,在这种情况下,DAO 使用第三方 API 提供数据访问机制。

    4.3. 增强User 

    最后,让我们创建用户类的UserSocialMedia 子类,以保留Tweet 对象的列表:

    1. public class UserSocialMedia extends User {
    2. private List tweets;
    3. // getters and setters
    4. }

    在这里,我们的UserSocialMedia 是一个复杂的域,其中包含User 域的属性。

    4.4. UserRepositoryImpl

    现在,我们将升级我们的UserRepositoryImpl  类,以提供User 域对象以及推文列表:

    1. public class UserRepositoryImpl implements UserRepository {
    2. private UserDaoImpl userDaoImpl;
    3. private TweetDaoImpl tweetDaoImpl;
    4. @Override
    5. public User get(Long id) {
    6. UserSocialMedia user = (UserSocialMedia) userDaoImpl.read(id);
    7. List tweets = tweetDaoImpl.fetchTweets(user.getEmail());
    8. user.setTweets(tweets);
    9. return user;
    10. }
    11. }

    在这里,UserRepositoryImpl 使用 UserDaoImpl提取用户数据,并使用TweetDaoImpl提取用户的推文。

    然后,它聚合两组信息,并提供 UserSocialMedia 类的域对象,该对象对于我们的业务用例非常方便。因此,存储库依赖于 DAO 来访问来自各种源的数据

    同样,我们可以增强我们的用户域以保留Facebook帖子列表。

    5. 比较两种模式

    现在我们已经看到了DAO和存储库模式的细微差别,让我们总结一下它们的区别:

    • DAO 是数据持久性的抽象。但是,存储库是对象集合的抽象
    • DAO是一个较低级别的概念,更接近存储系统。但是,存储库是一个更高层次的概念,更接近域对象
    • DAO作为数据映射/访问层工作,隐藏丑陋的查询。但是,存储库是域和数据访问层之间的层,隐藏了整理数据和准备域对象的复杂性
    • DAO 不能使用存储库实现。但是,存储库可以使用 DAO 来访问底层存储

    此外,如果我们有一个贫乏的域,存储库将只是一个DAO。

    此外,存储库模式鼓励域驱动的设计,也为非技术团队成员提供了对数据结构的轻松理解

    6. 结论

    在本文中,我们探讨了 DAO 和存储库模式之间的差异。

    首先,我们研究了 DAO 模式的基本实现。然后,我们看到了使用存储库模式的类似实现。

    最后,我们研究了一个利用多个DAO的存储库,它增强了域解决业务用例的能力。

    因此,我们可以得出结论,当应用程序从以数据为中心转向面向业务时,存储库模式被证明是一种更好的方法。

    像往常一样,所有代码实现都可以在GitHub上使用

  • 相关阅读:
    【python】我用python抓取了19个一线城市三年的房价数据,并做了走势分析
    【FreeSwitch开发实践】在nodejs中用ESL连接FreeSwitch
    Flutter 单元测试例子
    嵌入式系统开发【深入浅出】 通讯基本概念
    【Spring】静态代理
    springBoot异步线程,父子线程数据传递的5种姿势
    微软推出的Microsoft Fabric 到底是什么?
    后端开发过程中的乐观锁和悲观锁怎么理解并选型?
    5081. 重复局面
    驱动开发,stm32mp157a开发板的led灯控制实验(优化),使用ioctl函数,让write/read函数的专注读写功能
  • 原文地址:https://blog.csdn.net/allway2/article/details/127129634