Tuo*_*nen 3 java orm spring domain-driven-design jpa
我熟悉由服务、实体和存储库组成的典型分层架构。服务操作由存储库保存的带注释的实体类。在这个模型中,实体类只是带有一堆 getter 和 setter 的贫乏数据容器。业务逻辑驻留在过程服务类中(由 spring 容器管理的单例)。
我正在学习 DDD 作为一个业余爱好项目。在 DDD 中,实体形成了一个丰富的域模型,它在聚合根方法(和值对象)中容纳了大部分业务逻辑。服务几乎只是协作实体、存储库和其他服务的协调者。丰富的域模型以真正的 OOP 方式强制执行业务约束和不变量,并提高代码的可维护性。此外,领域模型是六边形架构的核心,这意味着它只是 POJO,不依赖于源代码级别的技术或框架问题。
但 JPA 规范要求实体 bean 应该具有公共 getter 和 setter,本质上是一个贫乏的数据容器,与 DDD 域模型相对立。那么我应该将域逻辑捆绑在 JPA 实体内吗?或者在 DDD 上使用 ORM 时我应该维护两个不同的模型和映射逻辑吗?这些模型和映射逻辑应该位于项目级别的哪里?
为了维护 DDD,特别是要将域模型与数据库层解耦(因为两者都可能单独更改),您需要两个不同的模型。
然后,您需要某种存储库服务,它知道(即依赖于)您的域模型,并且可以进行某种双向映射。在实践中,即使这违背了纯粹的 DDD 知识,您也可能需要在域模型中提供某种帮助(即,对已知的内部结构进行转储并从这样的转储中恢复状态。)但它确实很难存储并在持久存储中恢复真正的黑匣子,除非您想要进行简单的对象序列化。
关于您在评论中提出的问题:
这正是问题所在:您要么将基础架构混合到域中,要么暴露内部数据。不知何故,每一位撰写 DDD 的作者都只是通过不谈论这个问题来躲过这一劫。两种变体都同样丑陋,但当您似乎尝试一种相当纯粹的 DDD 方法时,我将创建一个与域对象耦合的 DTO 对象,该对象可由基础设施层访问(例如,通过使用包保护访问)。但是,我不会授予对真实内部值的访问权限。通过这种方式,您可以将“损坏”限制在一个点上,并且可以根据需要随意更改实现细节。
将一些伪代码添加到答案中:
public class Invoice { // Domain class
// implementation details. @Rest of the world: none of your business!
private Person creditor; // other domain objects
private MonetaryAmount amount; // and value objects
// Corruption starts here
toInvoiceDto() {
InvoiceDto res = new InvoiceDto();
res.setCreditorId(creditor.getId()); // mapping into external representation
...
return res;
}
static Invoice fromInvoiceDto(InvoiceDto persistentSource) {
...
}
// Corruption ends here
// do real business :^)
}
public class InvoiceDto {
...
}
public class Repository {
public void saveInvoice(Invoice businessObject) {
// *very* roughly
InvoiceDto dto = businessObject.toInvoiceDto();
InvoiceEntity entity = someKindOfMapper.toEntity(dto);
entityManager.save(entity);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2313 次 |
| 最近记录: |