【问题标题】:Using a Single DTO object for projection使用单个 DTO 对象进行投影
【发布时间】:2018-05-03 13:23:14
【问题描述】:

我在不得不为每个实体对象使用单个 DTO 对象或 DTO 对象时遇到了麻烦。 例如,我有 3 个类:Book、Author 和 Publisher。

Book.java

@Entity
@Table(name = "tbl_book")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "description")
    private String description;

    other different fields...
}

Author.java

@Entity
@Table(name = "tbl_author")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "description")
    private String description;

    other different fields...
}

Publisher.java

@Entity
@Table(name = "tbl_publisher")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @Column(name = "description")
    private String description;

    other different fields...
}

MyDTO.java

public class MyDTO {
    private Long id;
    private String description;

    constructor id, description...
    getters and setters...
}

我只想使用 EntityManager 选择特定字段(id 和描述):

em.createQuery("SELECT NEW MyDTO(id,description) FROM Book");

但我的问题是我应该对所有投影使用单个 DTO 对象(即 MyDTO)吗?比如:

em.createQuery("SELECT NEW MyDTO(id,description) FROM Author");
em.createQuery("SELECT NEW MyDTO(id,description) FROM Publisher");

关于使用 DTO 进行投影的教程只是说使用 DTO 进行读取和使用实体进行写入,但它们并没有说明是否有单个对象 DTO。请您提供一个示例,为什么单个 DTO 或为什么每个实体都使用 DTO。谢谢!

【问题讨论】:

    标签: java hibernate pojo dto


    【解决方案1】:

    我从事 DTO 工作已经有一段时间了,我可以分享以下几点:

    • 尝试根据您的需求(抽象类和/或接口)构建 DTO 层次结构
    • 即使你的 BookDTO 'just' 扩展了一个超类(例如 AbstractIdDescriptionDTO),它总是更易读 (IMO),而且维护起来也不那么乏味,而且你不能将一个对象误解为另一个对象李>
    • 我从不使用new DTO 语法,而是实现了一个自动转换器

    【讨论】:

    • 你能举个例子实现自动转换器或url教程吗?
    • 我不能说太多细节,因为我是为客户设计的,但是您可以使用像 Spring 这样的适当框架(如果我没记错的话,我不会使用它),或使用反射 API 来探索您的实体并构建 DTO 对象。好消息是,假设您有 100 个相互关联的实体,使用反射您可以自动构建整个链。但是,我的实体模型非常复杂,对您来说,一个更简单的就足够了。
    • 感谢您的回复。我将尝试使用该 DTO 层次结构,并且应该阅读更多文档。 :)
    • 不客气。正如您在另一条评论中指出的那样,不要想太多,构建适合您的需要的东西:)
    【解决方案2】:

    在我看来,为每个字段创建一个 DTO。拥有一个 DTO 会极大地耦合您的对象。例如,如果在 Book 类中您将描述更改为其他内容,您的所有代码都将不再工作。

    即使您从为 DTO 想一个好名字开始,您也会发现问题。 “MyDTO”听起来不好,也没有显示出它的目的,但你将无法想出一个有意义的名字。

    最后但并非最不重要的一点是单一职责原则是一件好事,而使用一个 DTO 来呈现多个对象会破坏它。拥有一个代表不同类型对象的类不是一个好的做法,并且违反了 SOLID 原则。如果您的项目共享一些公共属性,最好有单独的类并为公共部分创建一个接口。这只是标准的 OOP 设计。与 DTO 无关

    这只是我的看法。我可能错了。

    此外,在 JPQL 查询中创建类似的 DTO 会使其难以编码且更难维护。您可以执行以下操作:

    .setResultTransformer( Transformers.aliasToBean( PostDTO.class ) ) 
    

    为您的查询或有其他方法可以做到这一点。

    【讨论】:

    • 您的观点是,从长远来看,每个类都有一个 DTO 对象会提高可读性和灵活性吗?请举个例子。对不起。如果没有相对的例子,我只是很难弄清楚这一点。
    • 我添加了更多信息。您将不同的对象(具有不同的目的)组合到一个类中——这违反了 OOP 原则。每个类代表一个对象。如果他们有共享的属性或方法,那么他们会共享一些接口;)
    • 我觉得关于这个 DTO 的事情想得太多了,忘记了基本的 OOP 概念。谢谢你。如果至少一天没有其他答案,我会接受你的答案。
    猜你喜欢
    • 2018-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    • 2015-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多