域对象中的持久性注释是不好的做法吗?

Hol*_*osa 32 java annotations domain-driven-design hibernate morphia

我意识到像Morphia和Hibernate这样的持久性框架依赖于域对象上的注释来实现它们的魔力.在某种程度上,在我看来,这是在域层中插入持久性问题,这是我们应该努力避免的.

这可能是我应该尝试使用外部配置文件或域模型中的单独DTO来避开的东西吗?或者,持久性和域层之间的这种小漏洞通常被认为是可接受的吗?

Dav*_*ess 13

在我使用Spring和Hibernate的现有系统的最新版本中,我已经开始涉及类似的问题了.在第一次实现Hibernate模型时,我努力通过数据访问对象将服务类中的应用程序逻辑与持久性逻辑分开.去年构建新系统时,我允许大多数持久性对象充当域对象,因为这是权宜之计.

然而,我正在根据不断变化的业务需求重新设计同一系统,我再次倾向于将这些问题分开.我只是进入新设计的几天,但我发现自己更喜欢有一个表示内存中关注对象的对象,而另一个基于持久性的对象用于将其状态更改存储到数据库中.例如,我有一个Lead持久性和ActiveLead跨越事务的并行.

我还不确定这是最好的方法,但它在直觉上是有意义的.我渴望有持久性无关的集合-不,persistence- 无知仍然存在驻留内存的跨数据库事务,而不考虑标准的CRUD简化对象--set.但据我所知,最终所有数据库操作都实现为CRUD.这两个世界必须相互碰撞,其诀窍在于让它们和谐共舞.

域对象上的Hibernate注释?在我看来,这是在易于实施和易于维护之间的良好折衷.

  • 这也使您有机会对持久性对象与内存中对象的状态进行更严格/更严格的操作.我试图非常了解界面的输入和输出,并以这种方式分离这些问题. (2认同)

viv*_*011 9

域对象中的持久性注释是不好的做法吗?

是的.随着NoSQL的兴起,你不能依赖单一的持久化策略.

例如,今天我将我的域对象(假设使用morphia)保存到MongoDB中.如果明天我想将域对象持久化到Neo4j怎么办?

或者,人们可能希望将域对象持久化到所有三种数据库,如关系(Postgres/MySQL),MongoDB(文档存储)和Neo4J(图形数据库),仅用于评估.

在所有这些情况下,最好有单独的持久性策略,而不仅仅依赖于域对象

最佳实践:将持久战略作为战略模式传递可能会有所帮助.但是在设计类/对象时必须要小心.


Mic*_*rdt 8

我最近在一个相当复杂的系统上工作,有一个单独的持久层,这是一个巨大的痛苦屁股,非常糟糕的可维护性.你基本上是在看YAGNI和单一责任原则之间的冲突.在我看来,YAGNI是更重要的一个(唉,也是更常被忽略的一个).

我要说在绝大多数情况下,如果你使用ORM,直接持久保存域对象要好得多,除非你有强制要求强制持久化实体的结构不同(如果它们具有完全相同的结构,没有理由将它们分开,除了象牙塔的论点).

确定:始终在单独的服务/ DAO层中执行实际的持久性(调用ORM函数)!这样,如果您发现需要它,以后很容易引入持久层.

  • 投票,我不同意.太多的注释指的是太多的问题,很多时候往往迫使你的班级结构进入不同的方向,加上行为,使你的班级很难阅读和维护,这很糟糕. (2认同)
  • @Sam这可能是一个有效的案例,我并不是说你在任何情况下都不应该有任何注释.只是在我的小而不好的经历中,单一责任比琐碎的YAGNI更重要(因为在大多数情况下映射非常容易).有人,我们,迫使域对象具有行为(需要某些数据字段,以一种方式构建),这也用作DB数据结构(需要数据字段,结构以另一种方式),请参阅obj- rel阻抗不匹配,以及一些XML注释,以防万一...方式2对我来说很多 (2认同)

Mik*_*mas 5

简短回答:我喜欢持久、丰富的领域对象。

长答案:

近 10 年来,我使用 Spring 和 Hibernate 在一个相当大的系统上工作~500k LOC。一开始,我们从“事务脚本”(参见 Fowler)方法开始,部分原因是我们不太信任 Hibernate。然而,在很短的时间内,我们开始信任 Hibernate,并且由于我早期在相当纯粹的面向对象方面的培训,我成为了结合领域驱动设计方法的瞬态持久性的忠实信徒。我们基本上开始认为我们的系统是由 ODBMS 支持的(有很多小漏洞:-))。

我称我们的架构为“领域内核”,因为 DDD 一书还没有写完。这是在 Hibernate 的早期,所以领域模型没有被注解污染。XML 映射中单独关注持久性。

同样,随着时间的推移,我们越来越擅长将行为向下推入领域层。我们有一个非常传统的控制器--> 服务--> dao--> 域分层方案,该方案通过编译时依赖项强制执行。随着时间的推移,我观察到这个模型非常适用于我们的系统,它代表了 401(k) 计划管理相当复杂的领域的各个方面,包括计划设置、交易、会计、合规性测试、销售、品牌推广等。具有(相对)透明的“神奇”持久性的丰富域模型是我们能够根据域模型中的现有功能构建新功能的关键。

我们的服务层只协调技术服务之间的交互(例如电子邮件、文件 I/O、排队等),并在必要时帮助跨域包。服务层还定义了事务边界(通过 Spring)。服务仅接收或发出 DTO 或原语。很多人讨厌它,因为它是 DRY 的一个突破,但我们发现它让我们在定义服务接口和使用它们的代码时保持诚实。它还使以后远程操作变得非常容易。

这种方法使我们能够用一个非常小的团队(我们是一个 Scrum 团队)构建高质量的软件。

所以,认为我是持久域对象的信徒。不知道我的故事是否有帮助,但我想分享。


小智 5

我相信如果我已经决定使用我将要使用的持久性框架,我会在我的域上使用注释,但是,如果你遵循六边形架构和TDD ,XML会更方便.如果您使用特定框架预先注释您的域,您将与持久性集成相结合,无法测试核心功能,目的是使技术/框架无关.