JPA实体和DTO的区别与联系

23

在这些情况下,帮助决定何时使用DTO和何时使用实体的一般想法是什么?

  1. UI /服务器端Java调用服务。它应该获取/发送实体还是DTO?
  2. Web服务调用服务。服务应该接受实体还是DTO?

我喜欢阅读传递实体的代码:

  1. 更简单地传递,不需要映射到DTO
  2. 不需要额外的类
  3. 与其他实体的关系已经定义,因此不需要将相关的DTO合并为一个DTO
  4. 只是POJOs

但是有人认为DTO映射到实体更安全,因为它是一种契约,实体可以更改为任何形式,而DTO将保持不变。例如,实体具有名称字段,DTO也具有名称字段。以后,如果要求更改,数据库表更改,实体也会更改,将名称更改为名字和姓氏。但是DTO仍将具有名称字段,即名字+姓氏。

因此,以下是使用DTO的优点列表:

  1. 从接受DTO的代码的角度来看向后兼容

我能想到的DTO缺点是:

  1. 必须定义DTO类和映射(可能使用dozer)
  2. 程序员必须分析何时使用DTO和实体,我的意思是将DTO传递给每个方法都很混乱
  3. 实体与DTO之间的转换开销以及反之亦然
  4. 我仍然不确定如何映射一对多关系。在JPA中,我们可以惰性初始化它,但在传递DTO时,我应该初始化它还是不初始化它。简而言之,DTO不能有延迟初始化代理,只包含值。

请分享你的想法..

谢谢!

以下是来自不同地方的一些引用

pro dto:

重用实体类作为DTO似乎很混乱。类的公共API(包括公共方法上的注解)不再清楚地定义它所呈现的合同的目的。当类被用作DTO时,它将最终具有仅相关的方法,而当类被用作实体时,一些方法将仅相关。关注点不会被干净地分离,事情会更加紧密耦合。对我来说,这是一个比试图节省创建的类文件数量更重要的设计考虑。

pro entity:

绝对不是!!! JPA实体被映射到数据库,但它们并没有与数据库“绑定”。如果数据库发生变化,您需要更改映射而不是对象。对象保持不变。这就是整个重点!
2个回答

6

出于以下原因,我建议选择DTO选项:

  • 服务接口应该独立于数据库,对一个的更改不应总是需要对另一个进行更改。
  • 您假设您的服务将始终由Java客户端调用。
  • 当对象在Web服务调用的另一侧时使用延迟加载效果不佳。

2
你能否澄清一下这个部分:“您假设您的服务始终会被Java客户端调用”?感谢您的深入回答。 - Bertie
如果我的实体没有逻辑,而且默认情况下非常简单,只有getter和setter、equals以及基本方法,如toString、equals、hash、clone、set...那怎么办?在Web服务中使用它们供其他语言使用是没有问题的。 - djmj

4
Pro DTO: 1. 大多数情况下,UI需要某些属性作为传递参数来描述UI状态。这些状态不需要持久化,因此不需要在实体中使用。
2. 业务逻辑应该在实体或实体的辅助类中处理。您不应该将其与UI /演示层或调用它的客户端共享。
3. 实体的更改有时不需要更改DTO,反之亦然。
4. 在UI服务中对DTO执行系统级别验证更容易,因此可以在不需要的情况下停止对业务服务的调用。
5. 当UI端接收DTO而不是填充了来自UI的数据的实体时,可以自由地实现/使用其他验证框架。
6. UI /演示层是松耦合的。
下面是使用DTO的示例流程:
UI-->MVC-->使用UI服务进行系统验证-->业务代理-->业务服务-->持久化。

一个深入的回答,我给你点赞! - Bertie
4
“业务逻辑应该在实体内部”……我无法同意这种说法。将业务层作为一个重要组成部分是出于让数据库层和包含业务逻辑的层之间实现关注点分离的考虑。如果将业务逻辑放置在实体中,会损害这种分离的效果。 - scottb
对于是否需要单独为业务验证层设置一个单独的层并没有硬性规定。通常情况下,将操作数据的方法保留在持有数据的类中(实体内部操作数据),这是相当普遍的做法。这使得我们的实体完全独立,从而使我们的业务验证和规则摆脱了任何依赖关系。 - Hammad Dar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接