DTO 的更好方法?

Posted

技术标签:

【中文标题】DTO 的更好方法?【英文标题】:Better approach for DTOs? 【发布时间】:2012-07-28 19:51:19 【问题描述】:

我正在使用 SpringMVC、JPA2 开发一个简单的论坛 Web 应用程序。 我创建了反映数据库表结构的 JPA 实体,例如用户、论坛、帖子等。

但在 UI 上显示数据时,我需要 DTO,因为我不能始终使用实体保存要在 UI 上显示的数据。

例如:更改密码屏幕。在这里我需要保存旧密码、新密码和确认新密码。但是用户实体不会有旧/新/确认密码字段,它只有密码。所以我需要创建 DTO,它们只是 Web 和服务层之间的数据载体。

我的问题是在创建 DTO 对象时,我应该将所有属性放在 DTO 本身中还是将实体包装在 DTO 中并添加所需的其他属性?

例如:对于编辑用户屏幕,

public class UserDTO

     private User user; // User is a JPA entity
     // setters & getters

有了这个,我可以将底层的用户实体传递给我的服务层。但是在将 UI 属性绑定到 DTO 时,我需要关联 PropertyEditors。

(或)

public class UserDTO

    private String userId;
    private String userName;
    private String password;
    // setters & getters

使用这种方法,我需要将 DTO 属性转换并复制到 JPA 实体中并传递给服务层。

哪种方法更好?或者有没有其他完全没有 DTO 的方法?

【问题讨论】:

【参考方案1】:

您的第一种方法仍然将实体对象本身带到表示层。如果您有额外的参数不是来自数据库,并且您的持久性上下文仍然可用,那么这种方法就足够了。

第二种方法需要重复代码,并不理想。

如果持久性上下文不可用,我建议使用 EntityManager.detach() 将实体从持久性上下文中分离出来,而不是创建一个并行的 bean 层次结构。

另一方面,如果数据来自表示层,您将需要从数据库加载实体(使用 find() 或类似的东西)并更新它,或将其合并()到持久化上下文中.

【讨论】:

但是像更改密码屏幕或显示带有一些聚合结果的帖子对象列表的屏幕这样的场景呢..这里我们需要 DTO..对吗? 为什么?如果您只需要 Entity 中的数据子集(您已经从数据库中获取了这些数据),那么使用整个 Entity 不会有任何额外的开销。如果你还需要其他实体,你也可以加载它们并将它们带到表示层。 在 DataGrid 的情况下,我必须显示 1 到 25 个记录(实体),保存当前页面是什么,总共有多少页等等。而不是将所有这些详细信息存储为单独的参数在请求(无论)范围内,我认为最好将它们存储在 DTO 中。 明白。编辑了我的答案以更好地反映您的需求。

以上是关于DTO 的更好方法?的主要内容,如果未能解决你的问题,请参考以下文章

在 3 层架构中使用 DTO [关闭]

java的几种对象(po,dto,dao等)

NestJS 与猫鼬模式、接口和 dto 方法问题

从@RestControllerAdvice @ExceptionHandler 方法返回 DTO

使用带有 DTO 的 HttpPost,邮递员无法调用 tht 方法

MVC4 DTO 和多对多关系与 WebAPI 的扩展方法