DDD、域实体/VO 和 JPA

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

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

蓝皮书说,存储库是一种表示域对象上的集合的方式,负责与基础架构层进行通信。我还在一些帖子中读到,基础设施层是你必须使用休眠,JPA或其他任何东西的地方。

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

口号说Spring-data-jpa是轻松创建存储库,前面的示例似乎将JPA注释合并到一个域对象(the )中。customer

样品是否正确?还是我说的对?

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

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

感谢您的澄清。


答案 1

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

如果您使用 JPA 注释来注释域对象,则持久性机制已经渗入了域。你已经将域结构绑定到持久性结构上,这并不理想。

您的(实现)可以将未注释的域类 () 映射到带注释的 JPA 表示形式 - JPA 客户。这会将注释排除在域类之外,因此更干净。它允许您独立于域结构改变 JPA 持久性结构。这种好处的代价是映射代码的复杂性。JpaCustomerRepositoryICustomerRepositoryCustomer

interface ICustomerRepository {}

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

class Customer {}

class JpaCustomer {}

答案 2

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

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

在基础设施层中,您将提供主体(例如),在基础设施层中,您可以将自己与技术(例如JPA)相结合。CustomerRepository

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


推荐