简体   繁体   English

Java Spring 启动 - JPA:StackOverflowError 与 @ManyToMany 关系

[英]Java Spring Boot - JPA : StackOverflowError with a @ManyToMany relation

I am currently developing an application with the API in JavaSpringBoot and I need to add relationships between users (friends).我目前正在JavaSpringBoot中使用API开发一个应用程序,我需要添加用户(朋友)之间的关系。 For this I made a many-to-many relation which contains two fields:为此,我创建了一个包含两个字段的多对多关系:

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)
);

When I connect with a user and add relationships: everything is fine, but if I connect to one of the accounts added as a friend by the other user, there is a StackOverflowError.当我与用户连接并添加关系时:一切都很好,但是如果我连接到另一个用户添加为朋友的帐户之一,则会出现 StackOverflowError。

I know it's because of the almost identical entries in the database, but I have no idea how to get my entity to be correct.我知道这是因为数据库中的条目几乎相同,但我不知道如何让我的实体正确。 Currently each user must add the other individually, I imagine that I have to make a friend request system but again I am blocked.目前每个用户都必须单独添加另一个,我想我必须创建一个好友请求系统,但我又被阻止了。 Do I have to make an "effective" field in my friend_relation table.我是否必须在我的friend_relation 表中创建一个“有效”字段。 If so, how do I use it?如果是这样,我该如何使用它? Should I create a specific entity for this table or leave it in the User entity?我应该为此表创建一个特定实体还是将其保留在用户实体中?

Currently, this is what my user entity looks like:目前,这是我的用户实体的样子:

@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<>();

}

When trying to modify my entity to avoid the error:尝试修改我的实体以避免错误时:

    @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;

I looked for resources on the internet but I did not find it, I may have searched poorly and I apologize in advance if the answer has already been given.我在互联网上寻找资源但我没有找到它,我可能搜索得不好,如果已经给出答案,我提前道歉。

If you can help me it is with great pleasure, thank you in advance!如果你能帮助我,我会很高兴,提前谢谢你! (And sorry for the Google Translate I preferred not to use my rough English)✌ (对于谷歌翻译我很抱歉,我不喜欢使用粗俗的英语)✌


Ok sorry update, i don't post the stake trace: https://pastebin.com/Ls2qRpU4好的抱歉更新,我不发布股权跟踪: https://pastebin.com/Ls2qRpU4

It happens when I get my user on the front side.当我让我的用户在前面时会发生这种情况。 I am trying to connect but I cannot because this error occurs.我正在尝试连接,但由于发生此错误而无法连接。

First of, I've noticed an @Data on your entity, which I suppose is from Project Lombok?首先,我注意到您的实体上有一个@Data ,我想它来自Project Lombok? Just be careful, Lombok generated methods can trigger lazy loading and there are problems with equals/hashCode for auto-generated IDs.请注意,Lombok 生成的方法可能会触发延迟加载,并且自动生成的 ID 的 equals/hashCode 存在问题。 (see here and here ) (见这里这里

Now to your problem:现在解决您的问题:

It's indeed a JSON serialization issue.这确实是 JSON 序列化问题。 You have circular references and Jackson runs in circles bc.您有循环引用,并且 Jackson 在公元前循环。 it doesn't know where to stop.它不知道该停在哪里。

You can either use a DTO projection where you resolve this circle yourself, like:您可以使用 DTO 投影来自己解决此圆圈,例如:

public class UserDto {
    public Integer id;
    public List<Integer> friends; // List of IDs
}

You can also use Jackson annotations to achieve almost the same thing, like @JsonIdentityInfo .您也可以使用 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<>();

}

When you have complex Entities with circular references or very large object trees, you often have to think hard about how to serialize them - especially when taking LazyLoading into account.当您有具有循环引用的复杂实体或非常大的 object 树时,您通常必须认真考虑如何对它们进行序列化——尤其是考虑到 LazyLoading 时。 I have spent a lot of time on this in complex professional projects.我在复杂的专业项目上花了很多时间。 Simple automatically generated DTOs and serialization sometimes don't cut it.简单的自动生成的 DTO 和序列化有时不会削减它。

I'm not an expert on this, so I'm sure others will give more accurate answers.我不是这方面的专家,所以我相信其他人会给出更准确的答案。 However, the problem seems to occur when mapping the entity to JSON.但是,将实体映射到 JSON 时似乎会出现问题。 You can't map to JSON a user with a collection of friend users that also have their friends in a fully mapped collection since that causes infinite recursion.您不能 map 到 JSON 一个用户的朋友用户的集合,他们的朋友也在一个完全映射的集合中,因为这会导致无限递归。 I would try to use Jackson annotations to make the serialization of the friends list produce a list of ids instead of a list of complete users.我会尝试使用 Jackson 注释来使朋友列表的序列化产生一个 id 列表而不是完整用户列表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM