数据传输对象和事务服务方法

Posted

技术标签:

【中文标题】数据传输对象和事务服务方法【英文标题】:Data Transfer Objects and transactional service methods 【发布时间】:2010-10-19 13:01:09 【问题描述】:

在通过 Hibernate 支持的事务服务方法传递数据时,是否有任何真正实用的方法可以避免使用 DTO?换句话说,DTO 是避免延迟初始化问题的唯一非 hacky 解决方案吗?

我认为 DTO 的两个流行替代方案以及我不太喜欢它们的原因是:

    在视图模式中打开会话。这我不喜欢,因为我想让服务方法真正具有事务性(即,当方法退出时,Hibernate 会话被提交并关闭)。这主要是因为如果我以后需要将服务发布为 Web 服务,我不想担心事务。

    通过服务方法而不是 DTO 传递域/业务对象,并急切地获取所需的属性/属性。这要好一些。然而,在具有复杂实体关系的非平凡领域对象层次结构中,急切的获取必须在某处停止。当它发生时,我看不出这不会很快变成一个完整的黑客攻击,用整个地方的引用 id 替换实体。

从可维护性的角度来看,我是否遗漏了什么或者 DTO 实际上是唯一可靠的方法?

【问题讨论】:

【参考方案1】:

真正端到端使用实体的唯一方法是使用比 OpenSessionInView 更复杂一点的东西。根据我的经验,您将不得不在应用程序级别手动管理休眠会话。 OpenSessionInView 只会为一个请求提供相同的会话。之后,您需要不断地重新连接到当前会话。看看 Seam 和对话,或者实现你自己的 Hibernate Session 管理。我们目前根据向导的开始和结束时间手动管理会话,并使用 Spring AOP 将会话及时附加到正确的线程(会话不是线程安全的,不能很好地与 AJAX 混合)

另一方面,WebServices 肯定需要某种形式的 DTO。我看不出有什么办法。实体可能看起来像 POJO,但实际上并非如此,序列化它们的范围从困难到几乎不可能。只需创建符合服务方法目标的 DTO 并完成即可。

我个人认为 DTO 模式并不可怕,如果您只是创建一个网站,那么端到端实体是可行的,它甚至可以为您带来一些性能,但如果您想要更灵活的架构,坚持使用 DTO。

【讨论】:

【参考方案2】:

存储库、服务和控制器应该是处理应用程序核心的地方(如果您愿意,Hibernate Session 当然可以用作整个存储库层)。

视图不应该处理您的应用程序核心,即域模型。他们不应该处理活动对象,而是处理活动对象的非活动、定制表示。视图应该只以他们需要的特定格式传递他们需要的数据。您应该为您的视图构建 DTO。这种模式也称为视图模型,与领域模型形成对比。

为了让您的生活更轻松,可能有一些库或框架可以从您的域模型对象自动映射到您的视图模型对象,然后再返回。在 .NET 中,目前正在开发一个名为 AutoMapper 的开源框架;我不确定 Java 有什么。

【讨论】:

我相信 Dozer 会自动将 Java 域对象映射到 DTO 或从 DTO 映射,但我自己从未使用过它。【参考方案3】:

如果您放宽关闭会话的要求,您仍然可以在视图中使用打开的会话,只需提交服务事务中的所有内容。该会话仍可用于延迟获取,但您的所有事务都将完成。但是,如果您要切换到 Web 服务,那么无论如何您都需要预先加载所有实体。 DTO 只是强迫您有意识地急切加载并防止意外懒惰。

所以,最重要的是,如果你小心点,你可以跳过这两种环境中的 DTO,但我可能会坚持开放会话,并担心 Web 服务真正成为要求时。

【讨论】:

让会话保持打开状态似乎是明智的。 Web 服务的棘手之处在于,如果实体对象树很深,则必须切断一些分支(以便稍后查询)或替换为引用 id。一旦你这样做了,你基本上就有了一个 DTO,即使它是在服务之外形成的。【参考方案4】:

我喜欢 DTO 的想法,但我一直觉得它们并没有被其他开发人员很好地接受或喜欢,因为正确实施这种方法一直到数据库通常需要付出很多努力。这就是我创建 Blaze-Persistence Entity Views 的原因,它允许您将 DTO 建模为以有效方式映射到 JPA 实体模型的接口。您可以将实体视图应用于查询,并且查询将以仅获取实际需要的状态的方式进行调整,而不是获取所有状态并在 Java 中映射。

通过使用实体视图,您不需要在视图反模式中打开会话,因为所需的结构已被急切地加载。由于不涉及实体对象,因此也不会出现延迟加载问题。

由于实体模型在早期开发阶段通常与 DTO 模型非常相似,因此我经常看到开发人员只是跳过创建单独的 DTO 模型,因为他们试图避免麻烦。一旦实体模型中涉及审计、统计或非规范化等横切关注点,或者实体模型中的数据量比实体用例的实际需要大得多,开发人员就会遇到问题。

对于我前段时间写的这件事,你肯定会喜欢blog post。

【讨论】:

以上是关于数据传输对象和事务服务方法的主要内容,如果未能解决你的问题,请参考以下文章

mysql事务数据库逻辑可以放在哪一层?

Java DAO 对象事务

Spring的事务机制

FreeSql (二十八)事务

数据库事务如何影响MSSQL Server的性能和吞吐量?

事务对象和命令对象