【问题标题】:Spring Entities should convert to Dto in service?Spring 实体应该在服务中转换为 Dto 吗?
【发布时间】:2015-12-04 08:49:37
【问题描述】:

在对此question 发表评论后。我开始研究,但我仍然感到困惑。
实体在返回控制器之前应该转换为 Dto 吗?对我来说,这听起来不太实用。

【问题讨论】:

    标签: spring spring-mvc


    【解决方案1】:

    我们谈论的是软件架构,并且一如既往地谈论软件架构时,有上千种做某事的方法以及关于什么是最好的方法的许多意见。但是没有最好的办法,一切都有优点和缺点。请记住这一点!

    通常你有不同的层:

    • 存储数据的持久层
    • 业务层对数据进行操作
    • 用于公开数据的表示层

    通常,每一层都会使用自己的对象:

    • 持久层:存储库、实体
    • 业务层:服务、域对象
    • 表示层:控制器、DTO

    这意味着每个层只能使用自己的对象,而永远不会将它们传递给另一个层。

    为什么?因为您希望每一层都与其他层分开。如果您要在控制器中使用实体,您的演示文稿将取决于您的数据的存储方式。这真的很糟糕。您的视图与数据的存储方式无关。它甚至不应该知道这一点或数据是如何存储的。

    想一想:您更改了数据库模型,例如您将一个新列添加到您的数据库表之一。如果您将实体传递给您的控制器(或者更糟糕的是:您的控制器将它们公开为 JSON),数据库的更改将导致您的演示文稿发生更改。如果实体直接公开为 JSON,这甚至可能导致 JavaScript 或其他使用 JSON 的客户端发生变化。因此,数据库中的简单更改可能需要更改 JavaScript 前端,因为您将层耦合得非常紧密。您绝对不希望在实际项目中出现这种情况。

    怎么做?你怀疑这是否实用,所以只是一个如何在(伪)代码中做到这一点的小例子:

    class Repository {
        public Person loadById(Long id) {
            PersonEntity entity = loadEntityById(id);
            Person person = new Person();
            person.setId(entity.getId());
            person.setName(entity.getFirstName + " " + entity.getLastName());
            return person;
        }
    }
    

    在此示例中,您的存储库将在内部使用实体。没有其他层知道或使用这个实体!它们是这个特定层的实现细节。因此,如果要求存储库返回一个“人”,它会在实体上工作,但它会返回一个域对象。因此,在需要更改实体的情况下,保存与 repo 一起使用的域层。正如您在名称的情况下看到的那样,域和数据库可能不同。虽然数据库将名称存储在名字和姓氏中,但域只知道一个名称。这是它如何存储名称的持久性的细节。

    控制器和 DTO 也是如此,只是另一层。

    【讨论】:

    • 感谢您非常清楚的解释。我将在此处考虑优点和缺点以进行下一个设计。对于我当前的项目,我不需要在 Persistence 层进行这么多的解耦。目前我在我的控制器中转换实体,似乎我迈出了错误的一步,我最好在服务类中这样做。
    猜你喜欢
    • 2017-04-04
    • 1970-01-01
    • 1970-01-01
    • 2012-07-09
    • 2019-04-22
    • 2018-09-14
    • 1970-01-01
    • 1970-01-01
    • 2014-07-20
    相关资源
    最近更新 更多