ManyToMany关系导致StackOverFlow错误

8 浏览
0 Comments

ManyToMany关系导致StackOverFlow错误

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

问题是-我有一个UserController(REST API)用于发送用户列表-它导致StackOverFlow错误。用户尝试加载角色,而角色又尝试加载用户,依此类推。

我的问题是-如何避免这种情况?我还看到很多类似的设计。例如:https://viralpatel.net/blogs/hibernate-many-to-many-annotation-mapping-tutorial/他们为什么没有遇到这样的问题?

错误信息:

java.lang.StackOverflowError: 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]

0
0 Comments

ManyToMany关系导致StackOverFlow错误的原因和解决方法

问题出现的原因是在json序列化过程中存在循环引用。解决方法是使用注解来排除两个字段中的一个,以防止循环引用。

在处理ManyToMany关系的时候,有时候会出现循环引用的问题,尤其是在进行json序列化时。这种循环引用会导致StackOverFlow错误的发生。为了解决这个问题,我们可以使用注解来排除其中一个字段,从而防止循环引用的发生。

下面是一个例子,展示了如何使用注解来解决循环引用的问题:

@Entity
public class A {
    @ManyToMany(mappedBy = "as")
    @JsonManagedReference
    private List bs;
}
@Entity
public class B {
    @ManyToMany
    @JsonBackReference
    private List as;
}

在上面的例子中,类A和类B之间存在ManyToMany关系。为了解决循环引用的问题,我们在类A中使用了@JsonManagedReference注解,而在类B中使用了@JsonBackReference注解。这样一来,当进行json序列化时,只会序列化类A中的字段,而忽略类B中的字段,从而避免了循环引用的问题。

通过使用注解,我们可以很容易地解决ManyToMany关系导致的StackOverFlow错误。这个注解可以帮助我们排除其中一个字段,从而避免循环引用的发生。这种方式非常简单且有效,可以确保我们的程序在处理ManyToMany关系时不会出现错误。

0
0 Comments

在使用ManyToMany关联关系时,可能会出现StackOverFlow错误。这个问题的出现原因是因为在实体之间建立了相互引用,导致循环调用,最终导致栈溢出。

解决这个问题的方法是将实体转换为DTO(数据传输对象),然后返回DTO而不是实体本身。通过返回DTO,可以避免循环引用,从而解决StackOverFlow错误。

下面是一种解决方法的示例代码:

@Entity
public class EntityA {
    // other fields and annotations
    
    @ManyToMany(mappedBy = "entityAList")
    private List entityBList;
    
    // getters and setters
}
@Entity
public class EntityB {
    // other fields and annotations
    
    @ManyToMany
    private List entityAList;
    
    // getters and setters
}
public class EntityADto {
    // fields
    
    // getters and setters
}
public class EntityBDto {
    // fields
    
    // getters and setters
}
public class EntityConverter {
    public static EntityADto convertToDto(EntityA entityA) {
        // convert entityA to EntityADto
    }
    
    public static EntityBDto convertToDto(EntityB entityB) {
        // convert entityB to EntityBDto
    }
    
    public static List convertToDtoList(List entityAList) {
        // convert entityAList to List
    }
    
    public static List convertToDtoList(List entityBList) {
        // convert entityBList to List
    }
}
@RestController
@RequestMapping("/api")
public class ApiController {
    @Autowired
    private EntityService entityService;
    
    @GetMapping("/entityA")
    public List getEntityAList() {
        List entityAList = entityService.getEntityAList();
        return EntityConverter.convertToDtoList(entityAList);
    }
    
    @GetMapping("/entityB")
    public List getEntityBList() {
        List entityBList = entityService.getEntityBList();
        return EntityConverter.convertToDtoList(entityBList);
    }
}

在上面的示例中,我们创建了EntityADto和EntityBDto来表示实体A和实体B的数据传输对象。然后,我们通过EntityConverter类中的方法将实体转换为DTO对象。最后,在ApiController中,我们使用EntityService获取实体列表,并将其转换为DTO列表返回。

通过将实体转换为DTO,并返回DTO而不是实体本身,我们可以避免ManyToMany关联关系导致的循环调用,从而解决StackOverFlow错误。

0