我一直在努力选择将JPA实体作为单独的类,而不是在单个有界上下文中与域实体一起使用。我面临以下选择
对带有域存储库的聚合根/Aggregates..etc使用单独的域类来包装Spring JPA存储库,并使用转换器映射JPA实体<>仅包含必需数据的域实体
除非在映射器/转换器中在域存储库中处理此延迟,否则将放弃惰性加载,但这太过分了。
保存对象时,可能会有相关的聚合根(一对多关系),后来以复杂的逻辑进行处理,我不得不极端地关心Domain实体的状态,以将其传递给域存储库,或者用所有相关数据填充它,或者简单地将其映射(在转换器中的另一种方法),而没有关系数据(级联不适用于JPA持久化)
即使在非常简单的用例中,也有很多重复的代码可以避免这种情况
或者使用JPA实体作为我的域实体,到目前为止,有很多类似的示例/观点
https://github.com/citerus/dddsample-core/tree/Spring_Annotations_Autowire
http://www.javamagazine.mozaicreader.com/MayJune2018/Twitter#&pageSet=50&page=0
Should JPA entities and DDD entities be the same classes?
DDD, domain entities/VO and JPA
How to implement DDD using Spring Crud/Jpa Repository
另一方面,有这样的观点
Is it a good practice to use JPA entities as domain models?
从长远来看,我的问题来自经验
答案 0 :(得分:1)
什么会花费更多的精力和时间?
去耦几乎总是如此。这是个权衡!
两种方法都可以接受吗?
是的。我看到两种方法都有很多矛盾的意见,但实际上,它们只是意见而已。两者都适用且成本高。
两者的优缺点是什么?
将JPA实体用作域实体实际上确实在1上减少了时间成本。 2-还可以让您将延迟加载与关系一起使用,从而避免了应用程序服务中的更多代码,如果您不是按照id来引用其他聚合,那么这也是基于意见的,但实际上会浪费JPA。
这种方法的缺点是我认为它是单元测试。单元测试不应依赖于启动容器,数据库等。应该纯粹测试业务逻辑。但是,使用这样的框架并不是不可能的。例如,请参见此答案
JPA Entity must be unit tested and how?
将JPA用作具有包装器存储库的基础结构中的独立实体,将使单元测试更容易模拟数据并轻松地测试纯域(业务规则)。与以前的优点相反,它将花费您大量的映射工作和时间,太多的重复代码用于映射,包装存储库等。照顾域实体的状态令人头疼(这应该是专家),因为将null映射到JPA实体会影响到映射到持久性源的关系,并且您应该全面照顾 >表示域实体的状态。
也不会轻易使用ORM的自动延迟加载。要么
1-您在聚合根目录中引用了其他聚合作为成员(违反了聚合ID引用规则),并在映射器中进行处理
2-您可以从存储库中获得仅需要聚合根的所需数据,而其他聚合ID作为参考成员。这是通过存储库实现中定义良好的查询完成的,因此,这是很多编写和自定义查询的过程。避免使用默认实例,该默认实例会返回完整的JPA实体,并具有与延迟加载相关的参考。