将jpa实体转换为可靠资源的良好策略是什么

2022-09-01 14:23:02

Restful 资源并不总是与 jpa 实体进行一对一的映射。正如我所看到的,我试图弄清楚如何处理一些问题:

  1. 当资源具有由多个实体填充和保存的信息时。
  2. 当实体中包含要作为资源向下发送的详细信息时。我只能使用Jackson的,但我仍然有问题1,3和4。@JsonIgnore
  3. 当实体(如聚合根)具有嵌套实体,并且您希望包含其部分嵌套实体,但仅包含一定程度的嵌套作为资源时。
  4. 当一个实体的一部分属于一个父实体时,当其一部分属于另一个父实体时,当其一部分为另一个父实体时,要排除一个单独的部分时。
  5. 爆炸循环引用(我得到的主要是使用杰克逊的JSOG@JsonIdentityInfo)

可能的解决方案:我能想到的处理所有这些问题的唯一方法是创建一大堆“资源”类,这些类将具有构造函数,这些构造函数采用所需的实体来构造资源,并在其上放置该资源所需的 getter 和 setter。这是不是太过分了?

为了解决 2、3、4 和 5,我可以在将实际实体发送给 Jackson 之前对实际实体进行一些预处理和后处理,以将我的 pojo 序列化或反序列化为 JSON,但这并不能解决问题 1。

这些都是我认为其他人会遇到的问题,我很好奇其他人想出了什么解决方案。(我目前正在使用JPA 2,Spring MVC,Jackson和Spring-Data,但对其他技术开放)


答案 1

结合使用 JAX_RS 1.1 和 Jackson/GSON,您可以直接将 JPA 实体公开为 REST 资源,但会遇到无数问题。

DTO,即对 JPA 实体的投影是要走的路。它允许您将 REST 的资源表示问题与 JPA 的事务问题分开。您可以显式定义表示的性质。如果仔细设计 DTO/投影,则可以控制制图表中显示的数据量,包括要遍历的对象图的深度。您可能需要为同一 JPA 实体创建多个 DTO/投影,这些资源中的实体可能需要以不同的方式表示。

此外,根据我的经验,在 JPA 实体上使用和这样的注释并不能完全提供更可用的资源表示。在将对象合并回持久性上下文时,最终可能会遇到麻烦(由于忽略了属性),或者您的客户端可能无法使用资源表示形式,因为对象引用可能无法理解为方案。大多数JavaScript客户端通常难以使用注释生成的对象引用,因为这里缺乏标准化。@JsonIgnore@JsonIdentityInfo@JsonidentityInfo

通过DTO/预测还可以实现其他方面。JPA 不能自然地适应 REST 资源表示。有些人主张使用 JAX-RS 注释在资源 URI 中唯一标识资源,但这对于大多数客户端来说并不是开箱即用的。矩阵参数毕竟只是一个设计说明,而不是一个标准(还没有)。使用 DTO/投影,您可以针对计算的 ID(可以是组成键的组合)提供资源表示形式。@EmbeddedId@MatrixParam

注意:我目前正在为REST开发JBoss Forge插件,其中存在部分或全部这些问题,并将在将来的某些版本中通过生成DTO进行修复。


答案 2

我同意其他答案,即DTO是要走的路。它们解决了许多问题:

  1. 层分离和干净的代码。有一天,您可能需要使用不同的格式公开数据模型(例如。XML)或接口(例如,非基于Web服务)。在域模型中保留每个接口/格式的所有配置(例如 ,)会非常混乱。DTO 将关注点分开。它们可以包含外部接口(Web 服务)所需的所有配置,而不涉及域模型的更改,域模型可以保持 Web 服务和格式不可知。@JsonIgnore@JsonidentityInfo

  2. 安全性 - 您可以轻松控制向客户端公开的内容以及允许客户端修改的内容。

  3. 性能 - 您可以轻松控制发送到客户端的内容。

  4. 诸如(循环)实体引用、延迟加载的集合等问题也会在转换为 DTO 时由您明确且有意识地解决。