Spring环境中的域驱动设计和事务

我曾经围绕贫血领域模型设计我的应用程序,因此我有许多存储库对象,这些对象被注入到大的,胖的,事务感知服务层。 此模式称为事务脚本。 它不是一个好的做法,因为它会导致程序代码,所以我想继续前进到域驱动设计。

在网上阅读了几篇文章后,听了Chris Richardson关于Parleys的演讲并阅读了POJO in Action的DDD章节,我想我得到了全局。

问题是,我不知道,如何在我的应用程序中组织事务。 Chis Richardson在他的书中指出:

表示层通过直接或间接通过façade调用域模型来处理来自用户浏览器的HTTP请求,正如我在前一章中描述的那样,它是POJO或EJB。

好到目前为止,但InfoQ上的Srini Penchikala 文章指出:

一些开发人员更喜欢在DAO类中管理事务,这是一种糟糕的设计。 这导致过于细粒度的事务控制,这不能提供管理事务跨越多个域对象的用例的灵活性。 服务类应该处理事务; 这种方式即使事务跨越多个域对象,服务类也可以管理事务,因为在大多数用例中,Service类处理控制流。

好的,所以如果我理解正确的话,存储库类不应该是事务性的,服务层(现在更薄)是事务性的(因为它曾经是在事务脚本模式中)。 但是如果域对象直接被表示层调用呢? 这是否意味着我的域对象应该具有事务行为? 以及如何在Spring或EJB环境中实现它?

这对我来说似乎有些奇怪,所以如果有人澄清这一点,我会很高兴。 谢谢。

到目前为止,我个人对使用Spring和Hibernate应用DDD的看法是拥有一个无状态的事务服务层并通过它访问域对象。 所以我这样做的领域模型根本不知道交易,完全由服务处理。

有一个示例应用程序,您可能会发现有助于查看。 看起来Eric Evans参与创建它。

看到这个非常有用的博客文章 。 它解释了如何在不失去Spring和JPAfunction的同时实现平滑的DDD。 它以@Configurable注释为中心。

我对这些问题的看法有点不受欢迎。 贫血数据模型实际上没有错。 您没有一个带有数据+操作的对象,而是有两个对象 – 一个包含数据,另一个包含操作。 您可以将它们视为一个对象 – 即满足DDD,但为了更容易使用,它们在物理上是分开的。 逻辑上它们是一样的。

是的,这打破了封装,但它不会让你使用一些’魔术’(aop + java代理)来实现你的目标。

至于交易 – 有一种叫做交易传播的东西。 Spring使用@Transactional(propagation=Propagation.REQUIRED)支持它。 见9.5.7 。 如果您希望事务跨越多个方法(多个对象),则可以相应地更改传播属性。

您也可以在适当的情况下在服务层中使用@Transactional ,但是当您想要使用简单的单步操作(如“save”)时,这可能会引入许多样机服务类。

我认为开始使用DDD和Spring以及如何处理事务的一个简单方法就是查看Spring Roo附带的一个示例应用程序。 Roo生成遵循DDD原则的代码。 它严重依赖于AspectJ。 我怀疑它是在SpringSource的重量级人物Ramnivas Laddad 在本次演讲中提出的想法(早在2006年)实施的。

很遗憾,我还没有熟悉Spring,但我会就你的DDD理解给出反馈。 阅读您的事务描述很明显,您不了解DDD尤其是Aggregate,Aggregate Root和Repository概念。

在DDD中,事务不能跨越聚合,因此一个聚合将始终具有一个事务。