Spring Boot「31」DAO 模式与 Repository 模式对比
我在 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 目的在于收集、准备域对象。
希望今天的内容能对你有所帮助。
转载自:https://juejin.cn/post/7201404175245541413