gpt4 book ai didi

java - 通过服务公开 JPA 实体

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:32:20 25 4
gpt4 key购买 nike

我们正在使用 AngularJS、Rest、JPA 开发 Web 应用程序。我已经阅读了一些关于域实体不应通过服务公开的文章。我知道这是紧密耦合,可能存在循环引用、关注点分离,这对我来说似乎是有效的。但后来我看到有关将 jpa 和 jaxb 映射应用于同一模型的文章,eclipseLink moxy 就是一个例子。

然后是 Spring data REST,它通过 rest api 公开 jpa 实体。(可能是 Spring Data REST 用于解决手头的不同问题)

所以我有点困惑。回答以下 2 个问题和其中一个比另一个更好的场景会有所帮助。

  1. 将 jaxb 和 JPA 注释应用到同一个领域模型有什么好处?这样做主要是为了避免中间出现 DTO层?

  2. 是否应该仅在开发需要公开 CRUD 操作并且实际上不涉及其他业务功能的应用程序时才使用 Spring data REST?

最佳答案

使用 DTO 需要一定的开销:必须创建 DTO 类;实体类必须在序列化之前映射到 DTO。

DTO 也“感觉不对”,因为它们似乎违反了“不要重复自己”的原则。查看一个实体和一个 DTO 并发现它们本质上相同是令人沮丧的。

因此,直接公开您的 JPA 实体可以减少代码并减少使用代码时的精神开销。您的 Controller 、服务和存储库都处理相同的类。

但是有一些问题:

  • 您的内部表示与您要向 API 用户公开的界面不匹配。

    真实示例:根文档是 article,子文档是 sections 的分层文档。在内部,每个文档都与可能为空的父文档有关系。

    直接通过 REST 接口(interface)公开此实体需要客户端发送 id(或 HATEOAS 中的 url)作为其提交实体的一部分以正确链接在一起文件。

    更好的方法是在创建子部分时让 api 用户 POST 到 /articles/{id}/sections/

  • 公开内部数据。

    您的实体可能包括标识符、磁盘上的路径等,它们并非真正供公众使用。在序列化时,您必须 @JsonIgnore 这些。反序列化时,您还需要手动从实体中填充这些内容。

  • 性能。

    与上面的点类似;也许您的实体包含一个大数据对象。您希望用户能够 POST 或 PUT 这些,但不应该要求他们下载对象只是为了阅读实体的其他字段。

  • 潜在的序列化问题。

    惰性加载集合是这里的典型失败案例。

  • 比必要的更复杂的序列化表示。

    现实世界的例子:一个实体,带有一组同义词;同义词取决于单词。直接序列化实体将导致:

    { "id":12, 
    "word": "cat",
    "synonyms": [
    { "id": 23,
    "synonym": "kitty"
    },
    { "id": 34,
    "synonym": "pussycat"
    }
    ]
    }

    更好的模型是:

    { "word": "cat",
    "synonyms": [
    "kitty",
    "pussycat"
    ]
    }
  • 同一类上有很多注释,这会降低清晰度。

    根据实体的复杂性,您可能有 JPA 注释(@Entity@Id@GeneratedValue@Column @ManyToMany@MappedBy 等)、XML 注释(@XmlRootElement@XmlType@XmlElement 等)、JSON 注释(@JsonInclude@JsonIgnore@JsonProperty 等)、和验证注释(@NotNull@Null 等)都在同一个类上。

由于所有这些问题,我通常使用 DTO。我手动将实体映射到 DTO,但有些项目试图让这更容易,比如 Dozer .

我可以想象使用 spring-data-rest 或直接暴露我的实体只有在我有非常简单的实体,它们之间没有太多关系,并且它们之间有很高的对应关系的情况下实体模型和我希望向用户公开的模型。

关于java - 通过服务公开 JPA 实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29630162/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com