我目前正在使用 JavaSpringBoot 中的 API 开发应用程序,我需要添加用户( friend )之间的关系。为此,我创建了一个包含两个字段的多对多关系:
CREATE TABLE friend_relation
(
fk_id_friend integer REFERENCES users (id) NOT NULL,
fk_id_user integer REFERENCES users (id) NOT NULL,
PRIMARY KEY (fk_id_friend, fk_id_user)
);
当我与用户连接并添加关系时:一切都很好,但是如果我连接到另一个用户添加为 friend 的帐户之一,则会出现 StackOverflowError。我知道这是因为数据库中的条目几乎相同,但我不知道如何让我的实体正确。
目前每个用户必须单独添加另一个,我想我必须创建一个好友请求系统,但我再次被阻止。
我是否必须在我的friend_relation 表中创建一个“有效”字段。如果是这样,我该如何使用它?我应该为这个表创建一个特定的实体还是将它留在用户实体中?
目前,这就是我的用户实体的样子:
@Entity
@Table(name = "users")
@Data
@Accessors(chain = true)
public class UserEntity {
@Id
@SequenceGenerator(name = "users_generator", sequenceName = "users_sequence", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "users_generator")
@Column(name = "id")
private Integer id;
[...]
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "friend_relation",
joinColumns = @JoinColumn(name = "fk_id_user", referencedColumnName = "id", nullable = false),
inverseJoinColumns = @JoinColumn(name = "fk_id_friend", referencedColumnName = "id", nullable = false)
)
private List<UserEntity> friends = new ArrayList<>();
}
尝试修改我的实体以避免错误时: @ManyToMany
@JoinTable(name="friend_relation",
joinColumns=@JoinColumn(name="fk_id_user"),
inverseJoinColumns=@JoinColumn(name="fk_id_friend")
)
private List<UserEntity> friends;
@ManyToMany
@JoinTable(name="friend_relation",
joinColumns=@JoinColumn(name="fk_id_friend"),
inverseJoinColumns=@JoinColumn(name="fk_id_user")
)
private List<UserEntity> friendOf;
我在互联网上寻找资源但没有找到,可能是我搜索得不好,如果已经给出答案,我提前道歉。如果您能帮助我,我将非常高兴,在此先感谢您!
(对于谷歌翻译我很抱歉,我宁愿不使用我粗糙的英语)✌
好的抱歉更新,我不发布股权跟踪:https://pastebin.com/Ls2qRpU4
当我让我的用户站在前面时会发生这种情况。我正在尝试连接,但我无法连接,因为发生此错误。
最佳答案
首先,我注意到一个 @Data
在你的实体上,我想它来自 Lombok 项目?请注意,Lombok 生成的方法可能会触发延迟加载,并且自动生成的 ID 的 equals/hashCode 存在问题。 (见 here 和 here)
现在你的问题:
这确实是一个 JSON 序列化问题。你有循环引用, jackson 在公元前循环运行。它不知道该停在哪里。
您可以使用 DTO 投影来自己解决这个圆,例如:
public class UserDto {
public Integer id;
public List<Integer> friends; // List of IDs
}
您也可以使用 Jackson 注释来实现几乎相同的功能,例如 @JsonIdentityInfo
. Here's an article about it.@JsonIdentityInfo(
generator = ObjectIdGenerators.PropertyGenerator.class,
property = "id")
@Entity
@Table(name = "users")
@Data
@Accessors(chain = true)
public class UserEntity {
@Id
@SequenceGenerator(name = "users_generator", sequenceName = "users_sequence", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "users_generator")
@Column(name = "id")
private Integer id;
[...]
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "friend_relation",
joinColumns = @JoinColumn(name = "fk_id_user", referencedColumnName = "id", nullable = false),
inverseJoinColumns = @JoinColumn(name = "fk_id_friend", referencedColumnName = "id", nullable = false)
)
private List<UserEntity> friends = new ArrayList<>();
}
当您拥有具有循环引用或非常大的对象树的复杂实体时,您通常必须认真考虑如何序列化它们 - 特别是在考虑 LazyLoading 时。我花了拍品 在复杂的专业项目中花费时间。简单的自动生成的 DTO 和序列化有时不会削减它。
关于Java Spring Boot - JPA : StackOverflowError with a @ManyToMany relation,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62585553/