写点什么

Spring Boot「24」DAO 模式与 Repository 模式

作者:Samson
  • 2022-11-04
    上海
  • 本文字数:1686 字

    阅读完需:约 6 分钟

我们在 DAO 模式 中介绍了如何将数据持久化层与业务层分离,并且介绍了如何在 DAO 模式中使用 JPA,以及如何使用泛型来优化 DAO 模式。今天我们将学习一种与 DAO 模式类似,但在使用 JPA 是经常会遇到的模式,称之为 Repository 模式。

01-Repository vs. DAO

Repository 模式与 DAO 模式对比:


  • DAO 是数据持久化的抽象;而 Repository 是一组对象的抽象;

  • DAO 是偏底层的概念,靠近存储系统,例如 DB;Repository 是偏高层的概念,靠近应用中的域对象,例如 POJO;

  • DAO 是数据映射、访问层,目的是消除丑陋的 SQL 语句;Repository 存在于域对象与数据访问层之间,目的是隐藏收集、准备域对象的烦琐细节;

  • DAO 不可通过 Repository 实现;但 Repository 可以使用 DAO 访问底层的数据存储;


if we have an anemic domain, the repository will be just a DAO.


如何理解这句话,主要结合对比中的第三条。Repository 为了收集、准备复杂的域对象,如果应用中仅有“贫血的”域模型(即简单的 POJO),所以没有抽象 Repository 层的必要。

02-Repository 示例

我们继续使用 DAO 模式 中使用的示例代码 Event 和 Message 类。


public interface EventRepository {    Event get(Long id);    void add(Event event);    void update(Event event);    void remove(Event event);}public class EventRepositoryImpl implements EventRepository{    private EventJpaDao eventJpaDao;
@Override public Event get(Long id) { return eventJpaDao.get(id); }
@Override public void add(Event event) { eventJpaDao.save(event); }
@Override public void update(Event event) { eventJpaDao.update(event); }
@Override public void remove(Event event) { eventJpaDao.delete(event); }}
复制代码


EventRepository 内部使用了一个 DAO 示例来完成数据的持久化。Event 和 Message 这两个实例类都是所谓的“贫血的”域对象,所以它们的 Repository 实现存在的意义并不是特别的明显,甚至有点冗余。


Repository 模式应对的场景,主要是复杂的域对象的准备、收集。接下来我们将定义一个复杂的域对象 ComplexEntity 来展示一下 Repository 主要应用场景。


public class ComplexEntity {    private Long id;    private String name;    private List<Event> events;    private Set<Message> messages;    /** 省略 getter / setter 以及构造器 */}
复制代码


从定义中能知道,ComplexEntity 涉及到多个表的查询及数据的整合。此时,为 ComplexEntity 定义对应 Repository 就比较合适。


public interface ComplexEntityRepository {    ComplexEntity get(Long id);    void add(ComplexEntity complex);    void update(ComplexEntity complex);    void remove(ComplexEntity complex);}
public class ComplexEntityRepositoryImpl implements ComplexEntityRepository {
private GenericDao<Event> eventDao; private GenericDao<Message> messageDao;
public ComplexEntityRepositoryImpl(GenericDao<Event> eventDao, GenericDao<Message> messageDao) { this.eventDao = eventDao; this.messageDao = messageDao; }
@Override public ComplexEntity get(Long id) {
final List<Event> events = eventDao.getAll(); final Set<Message> messages = new HashSet<>(messageDao.getAll());
final ComplexEntity complex = new ComplexEntity("" + id, events, messages); complex.setId(id); return complex; } /** 省略其他方法的实现 */}
复制代码


ComplexEntityRepositoryImpl 实现中使用 Message 和 Event 的 DAO 来进行数据库查询,并组成 ComplexEntity 实例。


注:上述实例中的代码只是用来展示复杂对象的 Repository 的作用,并无其他的业务含义。


通过上例应该也能理解,为什么在上节中对比 DAO 和 Repository 时强调,Repository 目的在于收集、准备域对象。

发布于: 刚刚阅读数: 3
用户头像

Samson

关注

还未添加个人签名 2019-07-22 加入

InfoQ签约作者 | 阿里云社区签约作者

评论

发布
暂无评论
Spring Boot「24」DAO 模式与 Repository 模式_Java_Samson_InfoQ写作社区