ManyToMany 关系导致 *** 错误

Posted

技术标签:

【中文标题】ManyToMany 关系导致 *** 错误【英文标题】:ManyToMany relationship leads to *** error 【发布时间】:2019-09-14 05:31:30 【问题描述】:

我有一个名为 User 的实体,它有一组角色。我还有一个 Role 实体,它有一组用户。(这只是一个用于学习目的的练习应用程序。)

public class User 

    private String firstName;
    private String lastName;

    @ManyToMany
    @JoinTable(name="user_role", 
            joinColumns=@JoinColumn(name="user_id"), 
            inverseJoinColumns=@JoinColumn(name="role_id"))
    private Set<Role> roles;

    //getters setters


public class Role 

    private String name;

    @ManyToMany(mappedBy="roles")
    private Set<Users> users;

    //getters setters


Table: User      (id, firstname, lastname....)
Table: Role      (id, name)
Table: User_Role (id, user_id, role_id)

问题是 - 我有一个 UserController (REST API) 来发送用户列表 - 它导致 *** 错误。用户尝试加载角色,而角色又尝试加载用户等。

我的问题是 - 如何避免这种情况?我也看到很多类似的设计。例如:https://viralpatel.net/blogs/hibernate-many-to-many-annotation-mapping-tutorial/

他们怎么没有遇到过这样的问题?


java.lang.***Error: null
    at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_191]
    at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_191]
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_191]
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:468) ~[na:1.8.0_191]
    at java.net.URLClassLoader.access$100(URLClassLoader.java:74) ~[na:1.8.0_191]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:369) ~[na:1.8.0_191]
    at java.net.URLClassLoader$1.run(URLClassLoader.java:363) ~[na:1.8.0_191]
    at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_191]
    at java.net.URLClassLoader.findClass(URLClassLoader.java:362) ~[na:1.8.0_191]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_191]
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349) ~[na:1.8.0_191]
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_191]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:737) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.8.jar:2.9.8]
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.8.jar:2.9.8]

【问题讨论】:

如果将用户返回为json,则需要添加json注释以忽略角色的用户字段...否则json库(gson?)会进入这个无限循环 你能告诉我们你的堆栈跟踪吗?可能是序列化时出错。 @antoine.lange 是的。它发生在我们序列化时 您可以查看***.com/questions/3325387/…了解更多详情 Infinite Recursion with Jackson JSON and Hibernate JPA issue的可能重复 【参考方案1】:

我想在 json 序列化过程中有一个循环引用。 因此,您需要使用@JsonIgnore 注解从序列化过程中排除这两个字段之一。

在此处查看之前的回复:https://***.com/a/39985263/2311723

【讨论】:

【参考方案2】:

或者您可以将您的实体转换为 DTO(数据传输对象)并返回 DTO。我建议不要直接返回实体

【讨论】:

以上是关于ManyToMany 关系导致 *** 错误的主要内容,如果未能解决你的问题,请参考以下文章

休眠中ManyToMany关系的无限递归

Autotools 套件错误放置“man”文件导致安装失败

如何在Java-EE中使用hibernate实现ManyToMany关系?

为啥@ManyToMany 会导致 NullPointerException?

@ManyToMany 关系不保存

spring jpa ManyToMany 理解和使用