Jpa实体作为领域模型

4
根据DDD或六边形架构的推荐实践,领域模型应与更多关联于实际使用技术的数据模型表示(如表/列名称、连接等JPA注释)分开。这里存在一个实际问题——在这个模型中如何执行乐观版本控制?比如说,你有一个领域服务对领域模型进行读取-更新-保存操作。现在,JPA实体可能具有不能向上传递的版本列。因此,当保存调用到达存储库时,存储库再次进行(模型-->实体)转换和读取+更新操作时,它将无法确定最初读取实体的哪个版本。 第二个问题涉及性能方面,需要进行额外的读取。
2个回答

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

没有适用于项目中DDD的万能解决方案。这取决于您的需要和期望。

我应该尽快完成吗? 我可以花点时间来进行持久性到领域转换吗?

此代码是否由以后要更改的人使用,如果我不对其进行“锁定”,他们是否可能进行奇怪的操作?

我是否尝试创建纯DDD实现?

我应该放松一些规则,以便逐步将DDD引入我的项目或团队中吗?

有关JPA和领域实体的有趣阅读内容:


你好Luca,你怎么样? 我也需要一个解决方案,我已经将域和实体分开,但是在所有保存之前都会查询JPA。我该如何实现缓存?你有示例吗? - Romario Pires
嗨!不,实际上并不是这样。回顾一下,我也意识到这个解决方案会带来很多额外的工作,这就是为什么我还建议了第三种方案,这实际上是我经常使用的方案。无论如何,您可以使用 Hibernate 的缓存。 - Luca Masera
我目前也是这样使用的,但我正在使用需要Spring Save的Hibernate Evers。 - Romario Pires
你说的“它需要Spring保存”是什么意思?Hibernate和JPA与Spring是分开的,只是在第二个中,你可以直接通过应用程序上下文访问存储库bean。 - Luca Masera
1
在保存之前,检查数据是否已更改,以确保您的会话中的读取和写入之间不会丢失任何更新。如何以及为什么执行此操作,我认为可以在Hibernate的配置(以及实体注释)中进行管理。除此之外,我不知道更多了。我从未使用过,个人不喜欢JPA和Hibernate,因为它总是需要一定程度的“适应”,而您完全可以直接使用SQL来避免这种情况。 - Luca Masera

0

有不同的方法可以实现它。这主要取决于您的应用程序/层在架构中的位置。大多数情况下,与实体模型通信的应用程序/层位于基础级别。如果没有必要,则无需创建分离。通信的证明始终将是将与此层对话的层,因此我认为没有必要创建更多的转换。您可以只传递实体模型/实例数据。


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