【问题标题】:What is the best way to populate Entity from DTO从 DTO 填充实体的最佳方法是什么
【发布时间】:2019-04-02 04:45:36
【问题描述】:

我正在创建一个订单服务,这是 RestServices 世界的新手。

我需要将订单模型读入OrderDTO 并保存在数据库中。

为此,我有以下方法:

@PostMapping(produces = { MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE })
public ResponseEntity<OrderDTO> createOrder(@Valid @RequestBody OrderDTO orderDTO) {
    Order order = new Order(orderDTO);
    Order createdOrder = orderService.createOrder(order);
    OrderDTO createdOrderDTO = new OrderDTO(order);
    ResponseEntity<OrderDTO> responseEntity = new ResponseEntity<OrderDTO>(createdOrderDTO, null, HttpStatus.CREATED);
    return responseEntity;
}

一切正常,但我对当前的设计感到担忧:

  1. 我正在读取 DTO 的输入
  2. 将我正在转换的对象存储为将由 Hibernate 持久化的 Order 对象
  3. 再次发回响应,我将实际订单对象转换为 DTO。

最后我将为每个请求创建 4-5 个对象,如果我的应用收到 100 个请求,它可能会遇到内存问题。

如何读取模型数据并高效持久化?

【问题讨论】:

  • 每个请求创建 4-5 个短期对象不会遇到任何内存问题。而 100 个请求绝对不算什么。
  • 好的,感谢您的宝贵时间,有没有更好的方法来实现这一点?
  • 我不会将 JPA 实体耦合到 DTO。我不会将结果包装到 ResponseEntity 中。我会使用不同的 DTO 来表示用户提交的创建新订单的内容,以及您选择返回的内容来描述订单。
  • 我要强调将 DTO 与业务对象分开。他们不应该互相了解。通过让他们了解彼此,您将演示文稿 (DTO) 和服务/业务层(在您的 sn-p 中甚至是双向的)耦合在一起,这几乎总是一个设计缺陷。请注意,有些工具可以自动生成 DTO 和业务对象之间的映射工具。
  • 正如@jannis 所建议的,您可以使用 MapStruct 在 DTO 和实体之间自动生成映射器。对于设计,我认为你做得很好。

标签: spring rest spring-boot dto


【解决方案1】:

一般来说,更喜欢DTO,因为single responsibility principle,每个对象都有自己的职责,将视图/控制器与模型对象分开也更清晰

有时可以减少OrderDTO,使用既是DTD又是真实Object的对象,

它将包括 DTD 属性以及您可以使用构建器添加的其他属性,例如,当从请求创建对象时,我使用 @JsonIgnoreProperties(ignoreUnknown = true) 仅设置 DTD 属性,例如:

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonInclude(Include.NON_NULL)
public class Order 

您还可以使用JsonGetter/JsonProperty/JsonSetter 来控制预期/返回的内容

@JsonGetter 和 @JsonSetter 是 @JsonProperty 的旧替代品。

【讨论】:

  • 感谢您抽出宝贵时间为我提供启发。我有一个疑问,为什么人们更喜欢使用 DTO?
  • @Abdul 通常人们更喜欢 DTO,因为single responsibility principle,每个对象都有自己的责任。分开也更清楚
【解决方案2】:

我更喜欢 Mapstruct 之类的 Mapper:

OrderDtoMapper mapper = new OrderDTOMapper();

Order order = OrderDtoMapper.map(orderDto, Order.class);

然后返回:

OrderDTO createdOrderDTO = OrderDtoMapper.map(order, OrderDTO.class);

对我来说,代码看起来更具可读性......而且你没有太多可写的,因为 Mapstruct 会自动映射它。因为看起来你会映射很多;) 也许映射器值得一试:http://mapstruct.org/

【讨论】:

【解决方案3】:

我认为设计没有任何问题。

正如尼泽指出的那样。创建的对象是短暂的。

通常遵循 DTO 和实体设计以保持 UI 和服务层分开。

通过这种方式,您可以选择过滤掉敏感信息,使其不被传递给世界,例如密码、pin。

但如果您愿意,您可以直接在 Controller 类中使用 Order 实体。

我不建议这样做,但这是可能的。

【讨论】:

    猜你喜欢
    • 2015-12-18
    • 2012-08-30
    • 2021-05-20
    • 2018-09-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 2010-11-26
    相关资源
    最近更新 更多