DDD,领域实体/VO和JPA

21

我正在学习DDD,你可以想象我的大脑正在沸腾。

我的问题与我的领域对象(实体、VO等)有关,它们代表我的领域概念/逻辑以及如何持久化/检索它们。

《蓝皮书》说,仓库是表示域对象集合的一种方式,并负责与基础架构层通信。我在某些帖子中也看到,必须在基础架构层使用Hibernate、JPA或其他技术。

然后我看到了这个Spring-data-jpa示例http://spring.io/guides/gs/accessing-data-jpa/,我开始疯狂。

标语说Spring-data-jpa是为了轻松创建存储库,之前的示例似乎将JPA注释合并到域对象中(customer)。

这个示例是正确的吗?还是我是正确的?

如果我是正确的,那么领域和基础架构必须分开,这意味着要存储一个客户,我必须拥有:

  • 在我的域层中有一个Customer类(代表客户并具有所有逻辑操作)
  • 在我的域层中有一个CustomerRepository(从基础架构层检索或存储客户)
  • 在基础架构层中有一个Customer类,可能带有@Entity注释
  • 一些CustomerReposityJPA知道如何从数据库存储/检索客户。

感谢任何解释。


领域驱动设计。 - BAD_SEED
2个回答

17
在DDD中,仓储库(repository)是参与领域的一个对象,但实际上把一些后备存储抽象出来了。
如果你使用JPA注解注释你的领域对象,那么持久化机制就渗透到了你的领域中。这样会将你的领域结构和持久化结构绑定在一起,这并不理想。
你的 JpaCustomerRepository (实现了 ICustomerRepository) 可以将未注释的领域类 (Customer) 映射到一个带有注释的JPA表示的客户端 - JPA客户端。这样可以避免注解出现在你的领域类中,因此更加干净。它允许您独立地变化JPA持久性结构和领域结构。这种好处的代价是映射代码的复杂性。
interface ICustomerRepository {}

class JpaCustomerRepository implements ICustomerRepository {
     void save(Customer customer) {
          JpaCustomer jpaCustomer = map(customer);
          save(jpaCustomer);
     }
}

class Customer {}

class JpaCustomer {}

5
成本高,代码重复:需要映射属性的两个客户类。听起来像是很多样板代码。更换JPA提供程序是否有足够的理由来证明增加的努力值得呢? - Markus Pscheidt
3
我认为JPA注解是一种声明性信息。如果您需要更换JPA提供程序,将JPA注解从您的领域实体中删除有多困难? - Armando
4
成本高,代码存在重复——如果DDD客户与JPA客户实体相同,则存在代码重复。但是DDD客户应该是具有实际行为的对象,而不是像JPA实体一样的虚假对象(通常仅包含字段+getter/setter+ORM注释)。 - John Donn
我正在应用相同的概念。我的整个领域模型都没有框架特定的注释,完全与持久性无关。 但是,当在现有集合中添加/删除对象时,如何解决领域对象和数据对象之间的映射问题?https://dev59.com/OLroa4cB1Zd3GeqPprZ0 - user2054927
我同意,将JPA排除在领域之外的主要优点不是领域独立于持久性技术,而是独立于持久性结构。这将允许您在领域对象中使用继承和模式,如聚合和策略,而不是使用数据库条目的一对一表示。 - Elias Strehle

3

我看不到你发的链接,而且我从未在Java世界中应用领域驱动设计。 理论上,你需要在领域层中使用Customer聚合。在你的领域层中有存储库的空间(意为接口),所以你会有ICustomerRepository。 可能你会有四个常见持久性问题的原型:

GetById(CustomerId id);
Add(Customer c);
Delete(Customer c);
Update(Customer c);

在基础设施层,您将提供主体(例如CustomerRepository),在基础设施层中,您可以与某些技术耦合(例如JPA)。
领域层必须完全不知道基础设施中使用的技术。这样做可以完全更改实现细节而几乎不会出现问题。

1
有没有人看到过实现这个的示例项目?我似乎找不到任何样本,实际上在域层中建模了域实体(不一定与DB表相关),然后在基础设施层中使用JPA @Entity对象映射到db表。存储库接口应该在该基础设施模块中得到实现,并且应该知道如何将JPA实体映射到域模型中。 - Mustafakidd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接