likes
comments
collection
share

Spring Boot「31」DAO 模式与 Repository 模式对比

作者站长头像
站长
· 阅读数 14

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 16 天,点击查看活动详情

我在 Spring Boot「30」Web 应用中的 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 示例

我们继续使用 Spring Boot「30」Web 应用中的 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 目的在于收集、准备域对象。

希望今天的内容能对你有所帮助。