Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 将jpa实体转换为restful资源的好策略是什么_Java_Rest_Jpa_Jackson - Fatal编程技术网

Java 将jpa实体转换为restful资源的好策略是什么

Java 将jpa实体转换为restful资源的好策略是什么,java,rest,jpa,jackson,Java,Rest,Jpa,Jackson,Restful资源并不总是与jpa实体有一对一的映射。在我看来,有几个问题我正在设法解决: 当资源具有由多个实体填充和保存的信息时 当实体中有更多您希望作为资源发送的信息时。我可以使用Jackson的@JsonIgnore,但我仍然有第1、3和4期 当实体(如聚合根)具有嵌套实体,并且您希望包含其嵌套实体的一部分,但仅限于作为资源的特定嵌套级别时 当一个实体的一部分是一个父实体时,要排除该实体的一个部分,但当另一个实体的一部分是另一个父实体时,要排除该实体的一个单独部分 大量的循环引用(我主要是

Restful资源并不总是与jpa实体有一对一的映射。在我看来,有几个问题我正在设法解决:

  • 当资源具有由多个实体填充和保存的信息时
  • 当实体中有更多您希望作为资源发送的信息时。我可以使用Jackson的
    @JsonIgnore
    ,但我仍然有第1、3和4期
  • 当实体(如聚合根)具有嵌套实体,并且您希望包含其嵌套实体的一部分,但仅限于作为资源的特定嵌套级别时
  • 当一个实体的一部分是一个父实体时,要排除该实体的一个部分,但当另一个实体的一部分是另一个父实体时,要排除该实体的一个单独部分
  • 大量的循环引用(我主要是通过使用Jackson的
    @JsonIdentityInfo
    得到的)
  • 可能的解决方案: 我所能想到的处理所有这些问题的唯一方法是创建一大堆“资源”类,这些类将具有构造函数,这些构造函数使用所需的实体来构造资源,并在资源上放置必要的getter和setter。那是不是太过分了

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


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

    鉴于您的限制,除了数据传输对象,似乎没有其他解决方案-是的,人们将这种模式命名为……

    使用JAX_RS 1.1和Jackson/GSON的组合,您可以将JPA实体直接公开为REST资源,但您会遇到很多问题

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

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

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


    注意:我目前正在研究JBoss Forge插件for REST,其中一些或所有问题都存在,并将通过生成DTO在未来的某个版本中得到解决。

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

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

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

  • 性能—您可以轻松控制发送到客户端的内容

  • 转换为DTO时,您还可以明确地、有意地解决(循环)实体引用、延迟加载集合等问题


  • 如果您的应用程序是完全粗糙的,那么可以选择SpringDataREST,您完全不需要DTO。如果比这更复杂,那么使用DTO保护应用程序层会更安全。但不要试图将DTO封装在控制器层内。它们属于服务层,因为映射也是逻辑的一部分(应用程序中的内容和应用程序中的内容)。这样,应用程序层保持密封。当然,在大多数情况下,这可能是两者的混合。

    感谢您的详细回答。当我第一次看到这一点时,我看到一些人提到DTO是一种可能的解决方案,但通常在声明不应添加另一层之后就有评论。听起来,当您需要的资源不是现有jpa实体的一对一映射时,您不会为所有实体创建DTO。是吗?是的。简单对象模型