【问题标题】:getting infinite recursion with JPA hibernate by @OneToMany and @ManyToOne通过@OneToMany 和@ManyToOne 使用JPA hibernate 获得无限递归
【发布时间】:2020-04-08 06:49:03
【问题描述】:

我有一个无法解决的问题,我也用 JsonIgnore 尝试过,但也没有用。 我有一个待办事项列表,我希望我的任务输出我给他们的用户 ID。问题是因为每个用户都有一个任务数组,这些任务给了我一个无限循环的任务和用户。

这是我的代码:

用户:

@Entity
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

private String name;

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
private Set<Task> tasks;

任务:

@Entity
public class Task {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

private String name;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "user_id", nullable = false)
private User user;

然后我有普通的 getter 和 setter 以及一个 toString 方法。

【问题讨论】:

  • 注意:您的问题与 JPA 无关,您在序列化对象图时陷入了常见的“图不是树”陷阱。
  • 您正在寻找@JsonIdentityInfo。并且对于直接序列化数据库实体要非常谨慎;强烈考虑单独的 DTO 表示。 MapStruct 使翻译它们变得容易。

标签: java hibernate spring-boot jpa


【解决方案1】:

使用@JsonManagedReference 和@JsonBackReference

用户:

@Entity
public class User {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

private String name;

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
@JsonManagedReference
private Set<Task> tasks;

任务:

@Entity
public class Task {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

private String name;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id", nullable = false)
@JsonBackReference
private User user;

【讨论】:

  • 先生,jsonIgnore 在没有用户的情况下给我相同的任务输出。这些真的是唯一的解决方案吗?或者有没有办法在没有递归的情况下输出用户?
【解决方案2】:

在反序列化中,@OneToMany 或 @ManytoOne 关系字段也被调用。 最好为响应创建响应类而不是实体类并在其中设置您的实体值。

public class TaskResponse {
    private int id;
    private String name;
    private UserResponse user;
    ...setter getter
}
public class UserResponse {
   private int id;
   private String name;
   ...setter getter
}

【讨论】:

    【解决方案3】:

    尝试以下注释:

    //--1
    @OneToMany(mappedBy = "user", cascade = {CascadeType.ALL})
    @JsonManagedReference
    private Set`<Task>` tasks;
    
    //--2
    **@ManyToOne(cascade = CascadeType.ALL)**
    @JoinColumn(name = "user_id")
    @JsonBackReference
    private User user;
    

    【讨论】:

      【解决方案4】:

      我个人不喜欢混淆数据库表示和序列化等职责。在 JPA 中有一个双向图是完全可以的,唯一的问题是当您想将此双向图序列化为单向树结构时,这就是为什么我会根据您的用例为单向树创建第二个表示形式:有一个带有浅“用户”对象的“任务”,其中包含您在任务上下文中需要的那些值,或者有一个带有浅“任务”对象列表的“用户”,其中包含您在任务上下文中需要的那些值用户。

      【讨论】:

        【解决方案5】:

        我找到了解决方案, 我不得不将我的 getUser() 方法更改为:

            public int getUser() {
            return user.getId();
        }
        

        现在我只从任务中获取 userId,而不是从用户获取所有内容,这就是我不再获得递归的原因。

        我希望我能帮助现在也有这个问题并且在互联网上找不到任何解决方案的人

        【讨论】:

        • 在序列化时调用 getter 函数,这就是这个工作的原因。当您还需要用户对象时发生了什么?
        • 我只希望 userId 在前端向用户添加任务。但我现在会用你的答案试试
        • @DumiduUdayanga 不,因为它只会忽略我的用户,然后它不会输出任何用户。
        猜你喜欢
        • 1970-01-01
        • 2019-02-24
        • 1970-01-01
        • 2016-11-14
        • 1970-01-01
        • 2018-10-02
        • 2020-09-04
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多