使用 JPA 实体作为领域实体的洋葱架构

Onion Architecture using JPA Entity as Domain Entity

我一直在努力选择将 JPA 实体作为分离的 类 而不是在单个有界上下文中的域实体。我曾面临以下选择

使用分离域 类 聚合 roots/Aggregates..etc 与域存储库来包装 Spring JPA 存储库并使用转换器映射 JPA 实体 <> 仅具有所需数据的域实体

或者使用 JPA 实体作为我的域实体,到目前为止有多个 examples/opinions 这样的

https://github.com/citerus/dddsample-core/tree/Spring_Annotations_Autowire

http://www.javamagazine.mozaicreader.com/MayJune2018/Twitter#&pageSet=50&page=0

DDD, domain entities/VO and JPA

另一方面,也有这样的意见

Is it a good practice to use JPA entities as domain models?

我的问题,长运行,经验之谈

What would cost more effort & time ?

解耦几乎总是如此。这是权衡!

Are both approaches are acceptable as practices ?

是的。我看到对这两种方法有很多相互矛盾的意见,但实际上,它们只是意见。两者都是应用和成本。

What are the pros and cons of both ?

使用 JPA 实体作为域实体方法确实 1- 理论上减少了时间成本。 2- 还允许您使用带有关系的延迟加载来避免应用程序服务中的更多代码,如果您不遵循通过 id 引用其他聚合,这也是基于意见的,但确实会花费 JPA 的延迟加载。

我认为这种方法的一个缺点是单元测试。单元测试不应依赖于启动容器、数据库等。应该纯粹测试业务逻辑。但这对于这样的框架来说并不是最理想的。例如,请参阅此答案

使用 JPA 作为带有包装存储库的基础设施中的独立实体将使单元测试更容易模拟数据并舒适地测试纯域(业务规则)。它将与以前的优点相反,花费你的映射工作和时间,太多重复的映射代码,包装存储库等。它带来了令人头疼的问题(这应该是一个专业人士)关心域实体的状态是什么,因为空值到 JPA 实体的映射会影响到持久性源的关系映射,你 真的应该关心 用于您的域实体的状态。

此外,ORM 的自动延迟加载将不会被使用和轻松完成。要么

1- 您将对其他聚合的引用作为聚合根中的成员(违反聚合 ID 引用规则)并在映射器中进行处理

2- 您只需要从存储库中获取聚合根的数据,并将其他聚合的 ID 作为参考成员。这是通过存储库实现中定义明确的查询来完成的,因此,这是大量的编写和自定义查询。避免使用默认的 returns 完整的 JPA 实体和准备好的延迟加载相关引用。