将jpa实体转换为宁静资源的好策略是什么?

时间:2013-07-26 06:48:57

标签: java rest jpa jackson

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

  1. 当资源包含由多个实体填充和保存的信息时。
  2. 当实体中有更多信息要作为资源发送时。我可以使用杰克逊的@JsonIgnore,但我仍然会有问题1,3和4。
  3. 当实体(如聚合根)具有嵌套实体,并且您希望包含其嵌套实体的一部分但仅限于某一级别的嵌套作为您的资源。
  4. 如果要将实体的一部分排除在一个父实体的一部分之外,但在其不同的父实体的一部分时排除一个单独的部分。
  5. 抨击循环引用(我使用Jackson @JsonIdentityInfo
  6. 主要使用JSOG

    可能的解决方案: 我能想到的唯一方法是处理所有这些问题,就是创建一大堆“资源”类,这些类将拥有构造函数,这些构造函数需要实体来构建资源并为其上放置必要的getter和setter。 。那有点矫枉过正吗?

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

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

4 个答案:

答案 0 :(得分:25)

通过JAX_RS 1.1和Jackson / GSON的组合,您可以直接将JPA实体公开为REST资源,但是您将遇到无数问题。

DTO即对JPA实体的投射是可行的方法。它允许您将REST的资源表示关注点与JPA的事务关注点分开。您可以明确定义表示的本质。如果仔细设计DTO /投影,则可以控制表示中显示的数据量,包括要遍历的对象图的深度。您可能需要为同一JPA实体创建多个DTO /投影,以用于可能需要以不同方式表示实体的不同资源。

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

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

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

答案 1 :(得分:10)

我同意DTO的其他答案。他们解决了很多问题:

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

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

  3. 效果 - 您可以轻松控制发送给客户的内容。

  4. (循环)实体引用,延迟加载的集合等问题也会在您转换为DTO时明确且明知地解析。

答案 2 :(得分:1)

鉴于你的限制,似乎没有其他解决方案而不是数据传输对象 - 是的,它经常发生,以至于人们命名这种模式......

答案 3 :(得分:0)

如果您的应用程序完全是CRUDish,那么前进的方式绝对是Spring Data REST,您绝对不需要DTO。如果它比这更复杂,那么使用DTO保护应用层将更安全。但是不要试图将DTO封装在控制器层内。它们属于服务层,因为映射也是逻辑的一部分(您在应用程序中提供的内容以及您从中提取的内容)。这样应用层保持密封。当然,在大多数情况下,它可以是这两者的混合。