【问题标题】:Spring REST api - foreign key ID instead of entire objectSpring REST api - 外键ID而不是整个对象
【发布时间】:2020-10-08 15:48:32
【问题描述】:

我的 REST api GET 方法返回的 Json 有问题。

这就是我的实体的样子:

@Entity
public class Employee {
    ...
    @ManyToOne(fetch = FetchType.EAGER, optional = false)
    @JoinColumn(name = "department_id", nullable = true)
    private Department department;
}

@Entity
public class Department {
    ...
    @OneToMany(mappedBy = "department", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JsonBackReference
    private Set<Employee> employees;
}

这是我得到的答案,而我正在尝试通过其 id 获取员工:

{
    "id": 1,
    "surname": "smith",
    "department": {
      "id": 1,
      "name": "HR",
      "room": "13"
    }
}

现在,我想获得一个简单的 ID:"department_id": 1,而不是整个 Department 对象,我不知道该怎么做。

第二个问题:在这种情况下,REST api 中的good practise 是什么?我应该保持原样吗?只公开 id (我问你怎么做);还是使用 DTO 而根本不显示它? 此外,无论如何我都会将 _links 添加到该用户的部门,在这种情况下,我认为只留下 id 应该没问题(如果我错了,请告诉我)。 期待您的回答!

【问题讨论】:

    标签: spring-boot rest spring-rest


    【解决方案1】:

    一个好的做法是定义一个 DTO 来表示您的 API 公开的数据。 这应该与您的域(员工)分离,因为它将为您提供更大的灵活性,就像您想要实现的那样。

    class EmployeeDTO extends RepresentationModel {
        private long id;
        private String surname;
        private long departmentId;
    
       // getters and setters
    }
    

    这应该可行。当然,您需要将您的 Employee 实体映射到 EmployeeDTO。 RepresentationModel 包含 HATEOAS 所需的 _links 属性(例如,查看 https://www.baeldung.com/spring-hateoas-tutorial)

    关于从您的数据库中公开 id,我认为不这样做的一个很好的理由是您免费提供有关数据库大小的信息,而您可能不想这样做。甚至可以从中获得更多信息。

    您可以在这里找到关于该主题的精彩讨论: Exposing database IDs - security risk?

    我建议查看 UUID,它是一个通用唯一的字母数字标识符,不会公开有关您的数据的此信息。 更多关于 UUID:https://www.baeldung.com/java-uuid

    【讨论】:

    • 嘿,你能不能给个提示,或者举个例子,如何将Entity映射到扩展RepresentationModel的DTO?现在,使用 implements RepresentationModelAssembler&lt;Employee, EntityModel&lt;Employee&gt;&gt; 的类添加链接,然后在 toModel 函数中调用 EntityModel.of(employee);
    • @Nickname11 我回答了你的另一个问题,看看它是否适合你
    【解决方案2】:

    @JsonIgnoreProperties

    要在不更改任何实现的情况下获取部门 ID,您可以使用 @JsonIgnoreProperties({"name", "room"}),如下所示

    @ManyToOne(fetch = FetchType.EAGER, optional = false)
    @JoinColumn(name = "department_id", nullable = true)
    @JsonIgnoreProperties({"name", "room"})
    private Department department;
    

    它将以以下方式响应

    [
        {
            "id": 1,
            "surname": "smith",
            "department": {
                "id": 1
            }
        }
    ]
    

    您可能还想探索其他方法来实现相同的here


    最佳实践

    我们不应该公开和返回我们的模态和实体作为对 API 的响应。我们可能会创建 DTO/DAO 来接收和传输对象和数据。您还可以使用 mappersentity 转换为 DTODTO 转换为 entity

    在 DTO 的情况下,您可以只包含部门 ID,如果需要,可以使用存储库获取对象。

    【讨论】:

      猜你喜欢
      • 2015-06-29
      • 1970-01-01
      • 1970-01-01
      • 2021-05-26
      • 2014-12-11
      • 1970-01-01
      • 2021-01-05
      • 1970-01-01
      • 2022-11-11
      相关资源
      最近更新 更多