上一篇文章讲到了Specification这个特殊的类,它是用来封装搜索的条件,也讲到了它的实现。然而Specification和Repository二者的实现是相关的,那这次就来讲一讲Repository的实现。
预备知识
复习一下Repository是什么
从字面意思上讲repository是类似于仓库的意思。那在ddd中,它便是存放domain object (entity, value object)的东西。
需要指出的是它与service类的区别。Repository的职责仅是数据永久化。它将数据永久化的部分抽象,使domain层能够专注对业务逻辑的实现。那理所当然repository是不能够包含业务逻辑的,所以我个人不推荐在repository定义像下面那样的方法。
findPersonByName(String name);
findAllPersonsByGroup(Group group);
在repository中应该吧查询条件更加抽象化,而起到这个作用的便是我们之前讲到的Specification。
实现的前提: 分层架构
还是略微提一下我们实现的repository是基于分层设计这个架构的。
按照分层设计分为以下三层:
- application层
- domain层 <– 定义repository
- infrastructure层 <– 实现repository
实现repository
首先,这里仅谈论datasource是关系型数据库的实现。
repository和specifiction具体的实现其实是和db种类和选用的框架是有关系的,这里我们不能讲得面面俱到。
假设我们有一个表示商品的entity, Commodity。
public class Commodity {
private Long commodityId;
private String commodityName;
private String description;
/**
* 用于reconstruct的构造方法
*/
private Commodity(Long commodityId, String commodityName, String description){
this.commodityId = commodityId;
this.commodityName = commodityName;
this.description = description;
}
}
reconstruct
这里提一个概念叫reconstruct。
ddd中,domain object的实例化必须具有业务上的意义。很多情况下我们会用static的方法来表示其意义。比如
Commodity.createByName(commodityName);
这前我们还将过用Factory类来保证数据完整性。
但domain object还存在另一种实例化,那就是从db数据还原一个domain object。业务逻辑上没有因此增加一个domain object。只是将已经存在的domain object从repository里重新取出,故称作reconstruct。
我们为reconstruct定义了一个构造方法。请大家注意,这个构造方法仅用于还原domain object,在实现业务逻辑是我们原则上是不能调用这个构造方法的!
Commodity这个entity对应一个数据表commodities
id | commodity_name | description |
---|
接口定义
我们定义一个IRepository接口,那应该开放哪些方法呢。我们写一下大致的构思。
public interface I