gpt4 book ai didi

java - Hibernate : Infinite recursion,怎么解决呢?

转载 作者:行者123 更新时间:2023-11-30 07:47:16 27 4
gpt4 key购买 nike

我有一个非常烦人的无限递归问题。我的应用程序正在构建为 Spring Rest API,我使用 Lombok 生成构造函数以及 getter 和 setter。我的模型很少。

AppUser - 可能是最大的一个。

@NoArgsConstructor
@AllArgsConstructor
@Data
@Entity
public class AppUser {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String login;
private String name;
private String surname;
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
private String password;

public AppUser(String login, String password, UserRole userRole) {
this.login = login;
this.password = password;
this.userRoleSet = new HashSet<>();
this.userRoleSet.add(userRole);
}

public AppUser(String login, String name, String surname, String password) {
this.login = login;
this.name = name;
this.surname = surname;
this.password = password;
}

@OneToMany(mappedBy = "appUser",fetch = FetchType.EAGER)
private Set<UserRole> userRoleSet;

@OneToMany(mappedBy = "createdBy")
private List<Incident> createdIncidentsList;

@OneToMany(mappedBy = "assignedTo")
private List<Incident> assignedToIncidentsList;

@OneToMany(mappedBy = "postedBy")
private List<Comment> commentList;

@OneToMany(mappedBy = "appUser")
private List<IncidentChange> incidentChangeList;

}

事件

@Data
@Entity
public class Incident {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String description;
private LocalDateTime creationDate;
private IncidentStatus status;

@OneToMany(mappedBy = "incident", cascade = CascadeType.ALL)
private List<Comment> commentList;
@ManyToOne
private AppUser createdBy;
@ManyToOne
private AppUser assignedTo;
@OneToOne(cascade = CascadeType.ALL)
private ChangeLog changeLog;

public Incident(String title, String description) {
this.title = title;
this.description = description;
this.creationDate = LocalDateTime.now();
this.status = IncidentStatus.NEW;
this.commentList = new ArrayList<>();
this.changeLog = new ChangeLog();
}
public Incident(){

}
public Incident(String title, String description, LocalDateTime creationDate, IncidentStatus status, List<Comment> commentList, AppUser assignedTo, AppUser createdBy, ChangeLog changeLog) {
this.title = title;
this.description = description;
this.creationDate = creationDate;
this.status = status;
this.commentList = commentList;
this.changeLog = changeLog;
}

}

评论

@Data
@NoArgsConstructor
@Entity
public class Comment {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String description;
private LocalDateTime creationDate;

@ManyToOne
private AppUser postedBy;
@ManyToOne
private Incident incident;

}

变更日志

@Data
@Entity
public class ChangeLog {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne
private Incident incident;
@OneToMany(mappedBy = "changeLog")
private List<IncidentChange> incidentChangeList;

public ChangeLog(){
this.incidentChangeList = new ArrayList<>();
}

public ChangeLog(Incident incident, List<IncidentChange> incidentChangeList) {
this.incident = incident;
this.incidentChangeList = incidentChangeList;
}

}

事件变化

@Data
@NoArgsConstructor
@Entity
public class IncidentChange {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String description;
private LocalDateTime changeDate;

@ManyToOne
private ChangeLog changeLog;
@ManyToOne
private AppUser appUser;
}

简而言之,它是这样工作的:

AppUser 与 Incident、Comment 和 IncidentChange 具有
OneToMany 关系。

事件与 AppUser 有
多对一关系(重要的 TWICE),
OneToMany 到评论,
OneToOne 到 ChangeLog

评论与 AppUser 有
多对一关系,
ManyToOne 事件

ChangeLog 与事件具有
一对一关系,
OneToMany到IncidentChange

IncidentChange 与 ChangeLog 有
多对一关系,
ManyToOne 到 AppUser

我知道 AppUser 在 Incident 中,并且在嵌套在 Incident 中的 Comment 中,与 IncidentChange 的情况相同,但它嵌套得更深。

这是为想要检查 AppUser 和 Incident 是如何创建的人准备的代码 https://bitbucket.org/StabloPL/backendsimpleticketsystem/src/76e6bd107e68c82614fbc040b95f041fd7f51d28/src/main/java/com/djagiellowicz/ticketsystem/backendsimpleticketsystem/model/?at=masterIncidentController、AppUserControler 和 IncidentService、AppUserService 是某些人可能感兴趣的东西。

当我创建用户(通过 Postman 作为 JSON)并在之后获取它时,一切正常都没有问题。当我创建事件并将其分配给特定的人时,我无法获取事件,也无法获取该特定用户。其他页面,其中有没有创建事件的用户可以毫无问题地获取。这同样适用于没有分配 createdBy 用户的事件。一切都毫无问题地保存到数据库中。

这是当我尝试获取事件时 Hibernate/Spring 抛出的错误。当然剪了一点。

java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:472) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:129) ~[tomcat-embed-core-8.5.29.jar:8.5.29]
at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:129) ~[tomcat-embed-core-8.5.29.jar:8.5.29]


2018-04-24 11:39:43.731 ERROR 18300 --- [nio-8080-exec-4] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: com.djagiellowicz.ticketsystem.backendsimpleticketsystem.model.AppUser["createdIncidentsList"]->org.hibernate.collection.internal.PersistentBag[0]->com.djagiellowicz.ticketsystem.backendsimpleticketsystem.model.Incident["createdBy"]->com.djagiellowicz.ticketsystem.backendsimpleticketsystem.model.AppUser["createdIncidentsList"]->org.hibernate.collection.internal.PersistentBag[0]->
java.lang.StackOverflowError: null

我该如何解决?我必须知道 AppUser 发布了哪些评论,这同样适用于 Incident 和 IncidentChange,我不想从 Incident/IncidentChange/Comment 中删除这些信息

最佳答案

您必须覆盖 Lombok 的注释...当您使用 @Data 时,您会使用类中的所有字段隐式调用 @EqualsAndHashCode。无限递归从您用来映射关系的字段中产生。 @EqualsAndHashCode 在每个类中排除集合字段。例如,您可以在 AppUser 类上添加注释 @EqualsAndHashCode(exclude={"userRoleSet", "createdIncidentsList","assignedToIncidentsList","commentList","incidentChangeList"}) 以覆盖 @数据 默认策略。您必须对每个模型类执行此操作,直到没有无限递归错误为止。

此外...您的类之间存在循环依赖关系。当您序列化对象时,您应该删除所有循环依赖项。最好的解决方案是序列化 DTO 而不是实体。创建一个没有循环依赖的 DTO 应该可以解决这个问题。在序列化/反序列化过程中,您可以使用包含事件列表的 AppUserDTO,这是一个不引用 AppUser 的 IncidentDTO 列表。

关于java - Hibernate : Infinite recursion,怎么解决呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49998868/

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