为模型创建多个 DTO 是一个好习惯吗?

Nic*_*nda 9 java hibernate serializable dto

假设我有一个包含许多字段的User类:

public class User {
    public Integer id;
    public String name;
    public String username;
    public Integer age;
    public Address address;
    public String phoneNumber;
    public String email;
}
Run Code Online (Sandbox Code Playgroud)

但我并不总是需要前端的所有用户属性。每个屏幕只需要一些用户字段。为每个屏幕创建 DTO 类是一个好习惯吗,因为它们访问不同的属性?像这样:

class UserToScreenADTO implements Serializable {
    public String name;
    public String email;
}

class UserToScreenBDTO implements Serializable {
    public String phoneNumber;
    public Address address;
}

class UserToScreenCDTO implements Serializable {
    public Integer id;
    public String username;
    public String email;
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*kov 7

“仅”使用一个 DTO 或直接使用实体会产生高昂的成本,您通常只能稍后支付,因此我建议任何人为每个用例创建一个 DTO,就像您在这里所做的那样。

以下是一些原因/成本:

  • 如果 API 的用户看到未加载的状态访问器,这将触发延迟加载,从而导致性能不佳或延迟初始化异常。如果对象通过会话传递,您可能会丢失对象的上下文,因此您可能并不总是能够知道加载了哪个状态。
  • 一直加载所有数据可能效率很低。如果您有一些包含大量数据的文本列,则必须通过网络传输这些数据并将其具体化为 Java 对象等。如果您不使用这些数据,则加载它根本毫无意义。有人可能会说这是可以忽略不计的,但这取决于您的用例。可能发生的最坏情况?DBMS 执行全表扫描或效率较低的索引扫描,而不是仅索引扫描,因为您指示 DBMS 加载列的值。
  • 并非您想要为客户端提供的所有状态都应该在关系表示中。如果您进行聚合或使用表达式(例如将列连接在一起),则需要 DTO。

话虽如此,这是Blaze-Persistence Entity Views的完美用例。

我创建了这个库来允许 JPA 模型和自定义接口或抽象类定义的模型之间轻松映射,就像类固醇上的 Spring Data Projections 一样。这个想法是,您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

对于您的用例,使用 Blaze-Persistence Entity-Views 的 DTO 模型可能如下所示:

@EntityView(User.class)
public interface UserToScreenADTO extends Serializable {
    String getName();
    String getEmail();
}

@EntityView(User.class)
public interface UserToScreenBDTO extends Serializable {
    String getPhoneNumber();
    Address getAddress();
}

@EntityView(User.class)
public interface UserToScreenCDTO extends Serializable {
    Integer getId();
    String getUsername();
    String getEmail();
}
Run Code Online (Sandbox Code Playgroud)

查询是将实体视图应用于查询,最简单的就是通过 id 进行查询。

UserToScreenADTO u = entityViewManager.find(entityManager, UserToScreenADTO.class, id);

Spring Data 集成允许您像 Spring Data Projections 一样使用它:https://persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features


pet*_*rov 5

我将只创建一个 DTO 类,但例如将
我想要由后端拉取和设置的字段列表传递给其构造函数。
所有其他字段将为空。

字段列表将由前端传入。

我发现这种方法非常灵活/动态。

它还避免了维护多个类。

我不知道这种方法是否符合任何最佳实践或企业模式
,但创建多个 DTO 类听起来肯定更糟糕。