在使用JPA+Springboot开发过程中,由于用到ajax异步,在拿到数据后转json过程中,出现栈溢出的循环,分析得出是对象关联关系的问题。
在各种百度之后,得出的结论有很多
方法一:使用jsonIgnore注解
@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler","user","handler","villagers","planDetails","attachments","town"})
通过忽略关联关系来避免死循环。但是别太滥用,以至于所有entity都去用这个,根据需求用,否则,当你真很多地方都想要关联关系时,就开始养bug了
方法二:使用set(null)
通过set 把 对象的关联关系取消掉,即使从数据库查出来了,也可以null,不关联
比如A这个对象,有个user集合
a.setUsers(null);
这个,也还好,我没试过,当时灵机一动想到的,如果setnull还死循环,好像有一个配置在application.properties 的参数可以避免 之前百度到,没记住...提供个思路给大家
以上的方法其实并没有直面问题,而是在逃避。
方法三:使用@JsonIdentityInfo(generator=ObjectIdGenerators.UUIDGenerator.class,property="@id")
这个方法是我在百度的时候,找到的博客,博客地址:博客
通过每个json加id 来达到认清父子关系。 博客介绍的很详细,可以去看看
加了这个可能还不行,最好加上@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler"} 因为转json过程中会出现因为懒加载而出现如下错误
org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver.handleHttpMessageNotWritable(407) | Failed to write HTTP message: org.springframework.http.converter.HttpMessageNotWritableException: Could not write content: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: java.util.HashMap["ckRequirePartLists"]->java.util.ArrayList[0]->com.dyoon.cmms.pojo.CkRequirePartList["ckPurchaseBill"]->com.dyoon.cmms.pojo.CkPurchaseBill["applyOperator"]->com.dyoon.cmms.pojo.UserOperator_
所以加上 @JsonIgnoreProperties(value={"hibernateLazyInitializer","handler"}
最后贴个代码
import com.example.demo.domain.users.LoginUser;
import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonManagedReference;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;
import org.hibernate.validator.constraints.NotEmpty;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
@Entity
@Getter
@Setter
@JsonIdentityInfo(generator=ObjectIdGenerators.UUIDGenerator.class, property="@id")
@JsonIgnoreProperties(value={"hibernateLazyInitializer","handler"}
public class Committee extends NamedEntity implements Serializable {
@NotNull
private String bank;
@NotEmpty
private String account;
@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn(name = "user_id")
private LoginUser user;
@OneToMany(mappedBy = "committee", cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH})
private Collection villagers;
@OneToMany(mappedBy = "committee", cascade = {CascadeType.DETACH,CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
private Collection planDetails;
@OneToMany(mappedBy = "committee", cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH})
@JsonBackReference
private Collection plans;
@ManyToMany(mappedBy = "committees", cascade = CascadeType.ALL)
private Collection attachments;
@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinColumn(name = "town_id")
@Fetch(value = FetchMode.SELECT)
private Town town;
@Override
public String toString() {
return "Committee@" + hashCode() +
"(" + (isNew() ? "transient" : "persistent") + ")" +
"[id=" + id +
", name=" + name +
", bank=" + bank +
", account=" + account +
"]";
}
}