我们应该如何处理DTO?

How we should handle the DTO?

我有 2 个 table、PatientRegistration,并且是一对多关系。

在注册模块中,当我想编辑注册时,我调用 GetRegistrationByID(int id) 通过其 ID 获取数据以及 select PatientCodePatientName并将其解析为 DTO。

在另一个模块中,我重复使用了 GetRegistrationByID(int id) 但我需要更多关于患者的信息,例如性别、出生地点和日期、地址、村庄、地区、省和 phone没有。

对于这种情况,我有 2 个选项,更改 RegistrationDTO 以包含更多患者信息,但结果是在注册模块中调用 GetRegistrationByID(int id) RegistrationDTO 变得更大。因为我只需要PatientCodePatientName,现在多了一些不需要的信息

第二个选项是我创建另一个方法GetPatientInfoByRegistrationID(int id)但结果是有 2 次往返数据库。我认为它违反了 DTO 原则

A data transfer object (DTO1[2]) is an object that carries data between processes. The motivation for its use is that communication between processes is usually done resorting to remote interfaces (e.g. web services), where each call is an expensive operation.[2] Because the majority of the cost of each call is related to the round-trip time between the client and the server, one way of reducing the number of calls is to use an object (the DTO) that aggregates the data that would have been transferred by the several calls, but that is served by one call only.[2]

我正在努力学习如何使代码更好,那么我应该选择哪一个?请添加更好的解释

费用可能没有你想象的那么大。仔细检查此部分:

Because the majority of the cost of each call is related to the round-trip time between the client and the server, one way of reducing the number of calls is to use an object (the DTO) that aggregates the data that would have been transferred by the several calls, but that is served by one call only.

这告诉你的是DTO用于服务器和一些客户端之间的通信,这可能包括网络开销(我说可能因为在某些情况下它可能是一个相同的服务器,例如用于在向浏览器客户端生成 HTML 到 return 时填充服务器端数据的 DTO)。这就是为什么您希望将需要的信息包含在单个 DTO 中,而不是对所有内容都进行单独调用。例如,如果某些客户需要注册 患者信息,您希望避免让他们需要进行两次单独的调用,这就是为什么您 return 数据捆绑在一个 DTO。否则你将有两个完整的往返。但是,这并不意味着您需要不惜一切代价避免多次数据库查询。 DTO 是在服务器端编写的,在服务器上创建 DTO 的两个数据库查询不像需要两次完整的 client/server 往返那么戏剧化。

另一个考虑因素是,通常甚至不需要多个数据库查询。 Java Persistence API 等对象关系映射框架通常允许您映射实体之间的关系,并指定它们是延迟获取(仅在请求时)还是急切获取。 ORM 可以通过使用连接来优化 Eager fetch,使其只需要一个查询。仅仅因为 DTO 中有来自多个实体的信息,并不意味着它必然需要多个数据库查询。

然后是设计您的 DTO。不需要将所有信息集中在一个 class 中。 DTO 可以反映持久化的实体及其关系。在你的情况下,你有一个 PatientRegistration table,所以你可以有相应的 DTO classes,比如 PatientDTORegistrationDTO,其中患者 DTO 可以有一个注册列表,注册 DTO 是相关患者的一个字段。像这样的组合可以更容易地获取孤立的数据(例如,如果您只需要患者数据,而不需要注册数据)并重新使用 classes.

对于不同的数据集,您不一定需要不同的 DTO。仅仅因为一个调用应该只包含患者姓名和代码,而另一个调用包含更多信息,并不意味着您需要为此使用单独的 DTO classes。只需定义一个 class 即可保存所有信息(对于其对应的实体)并且只填写需要的内容。毕竟,客户通常知道他想从电话中得到什么。如果您希望能够区分因为不在数据库中而丢失的数据和根本没有映射的数据,您可以在每个字段上使用一些标记来指示它是否应该被设置。或者字段类型可能是一些包装器对象,在设置时会被标记,所以你现在可以判断它是 null 还是其他有意或无意的默认值。

最后,DTO 不一定需要遵循实体的结构或 属性 名称。它们首先是为客户设计的,所以要为此设计。 DTO 可以是抽象来隐藏客户端不需要知道的持久结构。但在实践中,保持实体和 DTO 相似(如果不完全相同)通常不会造成混淆。无论如何,设计良好的实体将具有清晰的结构和易于理解的属性。