Jpa 实体作为域模型

red*_*edi 4 dns domain-driven-design jpa hexagonal-architecture onion-architecture

根据 DDD 或六边形架构记录的推荐实践 - 域模型应该与与实际使用的技术(表/列名称、联接等、JPA 注释)更相关的数据模型表示分离。这里的一个实际问题是——如何在这个模型中进行诸如乐观版本控制之类的事情?假设您有一个域服务,可以在域模型上读取-->更新-->保存。现在,JPA 实体可能有一个无法向上传递的版本列。因此,当保存调用到达存储库并且存储库本质上再次进行(模型->实体)转换和读取+更新时,它将无法判断最初读取的是实体的哪个版本。
第二个问题是对此的性能考虑,涉及这里的一些额外阅读

Luc*_*era 5

你可以做不同的事情:

  • 放宽领域模型应与持久性模型分离的规则。没有人说 DDD 有应该严格遵守的“固定规则”。这意味着您将在域内使用相同的 JPA 实体,并按照 DDD 规则而不是 JPA 规则对它们进行建模。因此,每个字段都没有获取/设置,所有 ValueObject 的嵌入实体等等。但是,正如您所知,如果域很复杂,您就必须付出很多努力才能避免 JPA 陷阱。
  • 编辑:我不会建议这个解决方案,因为它需要很多额外的工作。由于可以使用hibernate的缓存,因此事情变得更简单。在将 JPA 实体转换为 Domain 实体之前,将其存储在缓存中。它看起来很愚蠢,但最终持久层和域层之间的分离允许您以任何对您有用的方式实现存储库。因此,如果您的 JPA 实体有一个版本,那么我想到的管理它的最简单方法是在存储库的实现中拥有一种缓存。然后你可以像这样继续:
    1. 读取 JPA 实体
    2. 将其存储在缓存中
    3. 发送更新的结果域实体
    4. 取回更新的域实体
    5. 更新缓存中的 JPA 实体
    6. 存储它,将版本处理留给 JPA
  • 忽略JPA的东西,直接使用SQL。您已经有了域实体,编写 SQL 使您可以自由地根据您的需求完美地调整代码,而无需 JPA 层的开销。您仍然可以使用缓存解决方案,在其中为每个 Id 存储您已读取的实体版本,并以与以前相同的方式使用它。

在项目中具体使用 DDD 并没有灵丹妙药的解决方案。这取决于您的需求和愿望。

我应该快点完成吗?我可以在域转换层的持久性上投入一些时间吗?

这段代码后来是否被某人使用/更改,如果我不加“锁”,它会做奇怪的事情?

我是否试图创建一个纯粹的 DDD 实现?

我是否应该放宽一些规则,慢慢地将 D​​DD 引入我的项目或我的团队?

关于 JPA 和域实体的有趣阅读: