问题 DDD,域实体/ VO和JPA


我从DDD开始,你可以想象我的大脑沸腾了。

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

蓝皮书说,存储库是一种表示域对象集合的方式,负责与基础架构层进行通信。我在一些帖子中也读到了infrastructura层,你必须使用hibernate,JPA或其他什么。

然后我看到这个Spring-data-jpa示例 http://spring.io/guides/gs/accessing-data-jpa/ 我变得疯了

该口号称Spring-data-jpa可以轻松创建存储库,之前的示例似乎将JPA注释合并到域对象中( customer)。

样品对吗?或者我是对的?

如果我是对的,域和基础设施必须分开,这意味着要存储我必须拥有的客户:

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

谢谢你的任何澄清。


2406
2017-07-14 07:34


起源

什么DDD意味着什么? - vels4j
域驱动设计。 - BAD_SEED


答案:


在DDD中,存储库是参与域的对象,但实际上是抽象出一些后备存储。

如果使用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 {}

10
2017-07-15 09:38



成本很高,代码重复:需要映射其属性的两个客户类。听起来很像样板代码。 JPA提供商的替代品有多大可能证明额外的努力是合理的? - Markus Pscheidt
我认为JPA Annotations是声明性信息。如果您需要替换JPA提供程序,从域实体中删除JPA注释有多难? - Armando


我看不到您发布的链接,我从未将域驱动设计应用于Java世界。 从理论上讲,你需要的是什么 Customer 在域层中聚合。在您的域层中,存储库(用作接口)有空间,因此您将拥有 ICustomerRepository。 对于常见的持久性问题,您可能会有四个原型:

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

在基础结构层中,您将提供正文(例如 CustomerRepository),在infrastracture层,你可以结合自己的技术(例如JPA)。

域层必须完全不知道基础结构中使用的技术。这样做你可以完全改变实现细节(几乎没有麻烦)。


2
2017-07-14 08:41



有没有人真正看到这样做的示例项目?我似乎无法找到任何实际上具有域实体(不一定与数据库表相关)的样本在域层中建模,然后在基础结构层中,映射到数据库表的JPA @Entity对象。存储库接口应该在该基础结构模块中实现,并且应该知道如何将JPA实体映射到域模型中。 - Mustafakidd