【发布时间】:2020-05-09 15:16:13
【问题描述】:
当我有用户并且他们有其他用户作为朋友时,我想制作类似于 facebook 的应用程序。所以我创建了一个实体User,它与自己有ManyToMany关系,他们也可以互相邀请到朋友列表中。不幸的是,当我想获取邀请朋友的用户时,我收到了这个错误:
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: java.util.ArrayList[0]->com.pk.thesis.devbook.models.dto.UserDTO["invitedFriends"]->java.util.ArrayList[0]->com.pk.thesis.devbook.models.dto.UserDTO["invitedFriends"]->java.util.ArrayList[0]-
... (it goes forever)
>com.pk.thesis.devbook.models.dto.UserDTO["invitedFriends"]->java.util.ArrayList[0]with root cause
我缩短的用户实体类:
@Data
@Entity
@Table( name = "users",
uniqueConstraints = {
@UniqueConstraint(columnNames = "username"),
@UniqueConstraint(columnNames = "email")
})
@JsonIdentityInfo(generator= ObjectIdGenerators.UUIDGenerator.class, property="@id")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NotBlank
@Size(max = 40)
private String username;
//other things...
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(name="tbl_friends",
joinColumns=@JoinColumn(name="personId"),
inverseJoinColumns=@JoinColumn(name="friendId")
)
private List<User> friends;
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable(name="tbl_friends",
joinColumns=@JoinColumn(name="friendId"),
inverseJoinColumns=@JoinColumn(name="personId")
)
private List<User> friendOf;
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable(name="tbl_invites_to_friends",
joinColumns=@JoinColumn(name="personId"),
inverseJoinColumns=@JoinColumn(name="invited_personId")
)
@JsonIgnoreProperties("invitationsToFriends")
private List<User> invitedFriends;
@JsonIgnore
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
@JoinTable(name="tbl_invites_to_friends",
joinColumns=@JoinColumn(name="invited_personId"),
inverseJoinColumns=@JoinColumn(name="personId")
)
@JsonIgnoreProperties("invitedFriends")
private List<User> invitationsToFriends;
}
如你所见,我试图让它变得懒惰,我也尝试了@JsonIgnore 注释,但没有任何效果。有什么建议吗?
我的返回 UserDTO 的方法(将用户映射到 UserDTO)
public UserDTO getUserDTO(String username) {
return userRepository.findByUsername(username)
.map(u -> modelMapper.map(u, UserDTO.class))
.orElseThrow(() -> new UsernameNotFoundException("User not
found"));
}
UserDTO 通过 org.modelmapper.ModelMapper 映射
public class UserDTO {
private String username;
private String firstname;
private String lastname;
private String email;
private List<UserDTO> invitedFriends;
private List<UserDTO> invitationsToFriends;
}
【问题讨论】:
-
您是否正在生成 toString() 方法,因为有时对实体的循环引用也会导致此问题。
-
@user06062019 来自 Lombok 的注释
@Data正在这样做 -
阅读错误信息。您没有序列化 User 的实例。您正在序列化 UserDTO 的实例。 User 类是完全不相关的。
-
当然它会获取它。懒惰并不意味着:此变量将始终包含一个空列表。重点是什么?懒惰的意思是:只有当您第一次调用此列表上的方法时,我才会执行填充该列表所需的 SQL 查询并填充它。我猜你的对象映射器(因为你还没有发布相关代码)将受邀朋友(用户)列表转换为受邀朋友 DTO(用户DTO)列表。为此,它遍历列表。所以它称之为 iterator() 方法。所以列表正在加载中。
-
然后在受邀好友列表中使用另一个 DTO,它没有受邀好友列表。或者确保不要填写他们的邀请好友列表。
标签: spring hibernate jpa recursion