spring-data-jpa一对多、多对多双向关联,查询操作的时候进入死循环问题

此处以多对多为例,解决查询时进入死循环问题

1.用户实体类

@Entity
@Table(name = "t_sys_user")
@Data
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private String fullName;
    private String email;
    
    @ManyToMany(cascade = CascadeType.REMOVE)
    @JoinTable(name = "t_sys_user_roles")
    private List<Role> roles;
}

2.角色实体类

@Entity
@Table(name = "t_sys_role")
@Data
public class Role {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String name;
    @Lob
    private String remark;

    @ManyToMany(cascade = CascadeType.REMOVE, mappedBy = "roles")
    private List<User> users;   //被维护端

}

在使用插入数据的时候没有任何问题,但是当查询的时候报错

java.lang.IllegalStateException: Cannot call sendError() after the response has been committed
	at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:472) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
	at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:129) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
	at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:129) ~[tomcat-embed-core-9.0.22.jar:9.0.22]
	...
	
java.lang.StackOverflowError: null
	at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_131]
	at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_131]
	at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142) ~[na:1.8.0_131]
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:467) ~[na:1.8.0_131]
	at java.net.URLClassLoader.access$100(URLClassLoader.java:73) ~[na:1.8.0_131]
	at java.net.URLClassLoader$1.run(URLClassLoader.java:368) ~[na:1.8.0_131]
	at java.net.URLClassLoader$1.run(URLClassLoader.java:362) ~[na:1.8.0_131]
	at java.security.AccessController.doPrivileged(Native Method) ~[na:1.8.0_131]
	at java.net.URLClassLoader.findClass(URLClassLoader.java:361) ~[na:1.8.0_131]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424) ~[na:1.8.0_131]
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335) ~[na:1.8.0_131]
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ~[na:1.8.0_131]
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:737) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:145) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:107) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.9.jar:2.9.9]
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.9.jar:2.9.9]
	...

返回的数据

[{"id":1,"username":"admin","password":"$2a$10$.UblZbe8b/ESRiXrajVgo.HuhbJUezsPgpyD.tVrJraFmegiup.aS","fullName":"管理员","email":"admin@qq.com","roles":[{"id":1,"name":"管理员","remark":"系统管理员","users":[{"id":1,"username":"admin","password":"$2a$10$.UblZbe8b/ESRiXrajVgo.HuhbJUezsPgpyD.tVrJraFmegiup.aS","fullName":"管理员","email":"admin@qq.com","roles":[{"id":1,"name":"管理员","remark":"系统管理员","users":[{"id":1,"username":"admin","password":"$2a$10$.UblZbe8b/ESRiXrajVgo.HuhbJUezsPgpyD.tVrJraFmegiup.aS","fullName":"管理员","email":"admin@qq.com","roles":[{"id":1,"name":"管理员","remark":"系统管理员","users":[{"id":1,"username":"admin","password":"$2a$10$.UblZbe8b/ESRiXrajVgo.HuhbJUezsPgpyD.tVrJraFmegiup.aS","fullName":"管理员","email":"admin@qq.com","roles":[{"id":1,"name":"管理员","remark":"系统管理员","users":[{"id":1,"username":"admin","password":"$2a$10$.UblZbe8b/ESRiXrajVgo.HuhbJUezsPgpyD.tVrJraFmegiup.aS","fullName":"管理员","email":"admin@qq.com","roles":[{"id":1,"name":"管理员","remark":"系统管理员","users":[{"id":1,"username":"admin","password":"$2a$10$.UblZbe8b/ESRiXrajVgo.HuhbJUezsPgpyD.tVrJraFmegiup.aS","fullName":"管理员","email":"admin@qq.com","roles":[{"id":1,"name":"管理员","remark":"系统管理员","users":[{"id":1,"username":"admin","password":"$2a$10$.UblZbe8b/ESRiXrajVgo.HuhbJUezsPgpyD.tVrJraFmegiup.aS","fullName":"管理员","email":"admin@qq.com","roles":[{"id":1,"name":"管理员","remark":"系统管理员","users":[{"id":1,"username":"admin","password":"$2a$10$.UblZbe8b/ESRiXrajVgo.HuhbJUezsPgpyD.tVrJraFmegiup.aS","fullName":"管理员","email":"admin@qq.com","roles":[{"id":1,"name":"管理员","remark":"系统管理员","users":[{"id":1,"username":"admin","password":"$2a$10$.UblZbe8b/ESRiXrajVgo.HuhbJUezsPgpyD.tVrJraFmegiup.aS","fullName":"管理员","email":"admin@qq.com","roles":[{"id":1,"name":"管理员","remark":"系统管理员","users":[{"id":1,"username":"admin","password":"$2a$10$.UblZbe8b/ESRiXrajVgo.HuhbJUezsPgpyD.tVrJraFmegiup.aS","fullName":"管理员","email":"admin@qq.com","roles":[{"id":1,"name":"管理员","remark":"系统管理员","users":
...

首先这是双向关联,双向关联中你如果从数据库里面查询一个User对象,那么User对象里面有Role,Role里面又有User对象,那么你用syso输出User对象,如果toString方法里面包含有输出User.roles的话,那么是必然会造成死循环的。如果你用sping mvc等框架将后台数据返回给前台也是同理,也会造成返回的JSON数据死循环

那么要如何解决?

解决办法就是在序列化实例的时候中断循环就好。首先你要理解这不是spring-data-jpa的问题,这是一个序列化的问题

例如如果是用jsckson对数据进行序列化的的话,可以使用下面的注解。

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 
@Entity
@Table(name = "t_sys_user")
@Data
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String username;
    private String password;
    private String fullName;
    private String email;
    
    @JsonIgnoreProperties("users")
    @ManyToMany(cascade = CascadeType.REMOVE)
    @JoinTable(name = "t_sys_user_roles")
    private List<Role> roles;
}

序列化用户类角色字段里的用户集合字段user.roles[i].users时就忽略该字段
注意:此处忽略的是roles中每个Role类中的User对象,并不忽略User类中的roles属性。
Role类修改如下:


	@JsonIgnoreProperties(value = { "roles" })
    @ManyToMany(cascade = CascadeType.REMOVE, mappedBy = "roles")
    private List<User> users;   //被维护端

返回的结果无user.roles[i].users字段

[{"id":1,"username":"admin","password":"$2a$10$.UblZbe8b/ESRiXrajVgo.HuhbJUezsPgpyD.tVrJraFmegiup.aS","fullName":"管理员","email":"admin@qq.com","roles":[{"id":1,"name":"管理员","remark":"系统管理员","permissions":[]}],"enabled":true,"version":0,"enabledStr":"有效","authorities":null,"accountNonExpired":true,"accountNonLocked":true,"credentialsNonExpired":true}]

问题解决!

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值