使用DTO与序列化实体

时间:2014-09-06 07:56:48

标签: json spring entity dto

在提出问题之前,我已经阅读了this线程,但这是一个非常古老的线程,现在有很多新的方法可以对这些实体进行序列化。

我的第一个问题是为什么我们不应该使用控制器中的实体?如果唯一的原因是废弃数据通过电线传输那么它应该不是问题,因为有办法避免这种情况。

我使用flexjson.JSONSerializer来序列化实体,使用Gson.fromJSON()将json序列化为实体而不是使用DTO。我的控制器代码看起来像这样..

@RequestMapping (value = "", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public void createStream(@RequestBody String  streamData) {
    StreamEntity streamEntity = null;
    try {
        streamEntity = streamService.createStream(streamData);
        logger.info("Created Stream [id=%s, name=%s]", streamEntity.getId(), streamEntity.getStreamName());
    } catch (Exception e) {
        logger.info("Error occured while creating the stream[name=%s]: %s",streamEntity.getStreamName(), e.getMessage());
    }               
}


@RequestMapping (value = "/{id}", method = RequestMethod.GET)
public String fetchStream(@PathVariable(value = "id")final Long id) {
    StreamEntity streamEntity = streamDAO.getById(id);
    String json = StreamEntitySerializer.serialize(streamEntity);       
    return json;
}

仅在控制器中使用实体的目的是用于记录。代码是否有任何错误/令人反感?

1 个答案:

答案 0 :(得分:5)

我认为你有两个问题......

问题1 :为什么不将实体暴露给控制器(又名表示层):

对于大型/复杂项目,它的不良形式是在控制器中使用实体,因为它会导致业务逻辑在您的项目中传播。将实体传递到Presentation层(也称为控制器)后,任何控制器都可以修改和保存数据。通常,多个控制器需要访问相同的实体。这导致代码维护地狱,因为现在你必须在多个地方维护你的数据CURD,反腐败和业务逻辑。将所有业务逻辑(操纵数据的逻辑)移动到公共包(即域\服务层)使得长期维护代码变得更加容易。通过将DTO向上传递到控制器,您将获得更清晰的代码,这更容易测试。以下是关于分层体系结构的精彩演示:https://www.youtube.com/watch?v=aZp7C971uC8

其他阅读:

问题2 为什么不序列化实体而不是将其转换为DTO并将其序列化。

有很多理由不这样做,但这里有一些令人浮现的想法。

  • 维护:通过直接公开您的实体,您可以在数据存储方式与客户获取的数据对象之间建立硬链接。例如,当您需要重命名/删除实体中的字段时会发生什么。更改数据库时会发生什么?如果实体转换为DTO,则在MySQL和Mongodb之间切换会更容易。

  • 测试:它比Hibernate实例更容易模拟DTO实例

  • 性能:即使您不需要公开该数据,序列化实体也可以触发从该数据库中提取的所有延迟加载字段。这可以很难追踪性能问题。 DTO使您明确了哪些字段已转换和序列化。此外,由于DTO通常更小更简单,这使得序列化更快。