com.fasterxml.jackson.databind.ser.std.CollectionSerializer.



在spring中,我的类之间有一些一对多的关系。当我试图获取所有数据时,这是一个类似无限递归的错误,下面是整个错误消息。

at com.fasterxml.jackson.databind.ser.std.CollectionSerializer.serialize(CollectionSerializer.java:25) ~[jackson-databind-2.9.6.jar:2.9.6]
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727) ~[jackson-databind-2.9.6.jar:2.9.6]
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719) ~[jackson-databind-2.9.6.jar:2.9.6]

我有两个类,它们通过OneToMany Relationship 相互连接

用户类别

public class User  {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@OneToMany(mappedBy = "User")
private List<Conversation> Conversation;

会话类

public class Conversation {
@Id  @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "User_id")
private User User;

结果截图

屏幕截图结果

我不知道为什么会发生这种情况,但也许是因为和Failure类的关系。

存储库类

@Query(nativeQuery = true, value = "SELECT * FROM `conversation` WHERE 1")
public List<Conversation> findAllConv();

控制器类

@Autowired
private ConversationRepository conv;

@GetMapping("/GetAllConversation")
public List<Conversation> getAllConv()
{
return conv.findAllConv();
}

完整跟踪

2021-05-14 12:58:57.306 ERROR 1540 --- [nio-8020-exec-1] w.s.e.ErrorMvcAutoConfiguration$SpelView : Cannot render error page for request [/survey/GetAllConversation/] and exception [Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: org.club.entities.User_$$_jvstf65_b["conversation"]->org.hibernate.collection.internal.PersistentBag[0]->org.club.entities.Conversation["user"]-

一般使用关系时,可以调整"获取";以及";级联";类型获取意味着,如果与要加载的条目相关的所有条目都已加载,而级联则与传递给相关对象的当前条目上的操作相关。

第1版:我建议您尝试将fetch类型设置为lazy,至少对于Conversation类:

@ManyToOne(fetch = FetchType.LAZY)

除此之外,我建议使用从CrudRepository继承的存储库,以便您可以使用派生查询。

第2版:在看到堆栈跟踪之后,问题就清楚了。Jackson试图将Conversation对象绑定到JSON,但由于User类中的Conversation引用,遇到了一个无休止的循环。

有两种方法可以解决这个问题。如果仍要插入Conversation引用的User对象,则可以添加@JsonIgnore注释。

@JsonIgnore
@OneToMany(mappedBy = "User")
private List<Conversation> Conversation; 

如果你根本不关心用户,那么你也可以将其添加到对话对象中的用户引用中:

@JsonIgnore
@JoinColumn(name = "User_id")
private User User;

如果以后遇到问题,还可以考虑将存储库返回的Conversation对象映射到专门为JSON映射而创建的特定数据传输对象。

根据stacktrace和数据模型判断,问题在于User和Converstaion类之间存在双向关系。

用户有一个对话项目列表,然后链接回用户。序列化时,这会创建一个无限循环:

序列化用户->序列化他的对话->序列化coveration.user->连载他的谈话等。

避免这种情况的一种方法是用@JsonIgnore注释converstaion中的User字段,这样在序列化用户时,你会得到他的对话,但由于Jackson会忽略引用,所以你不会从堆栈中得到错误。

异常消息在这里非常清楚:无限递归(StackOverflowError

我遇到了同样的问题,并通过以下方法解决了它。首先我有两节课。

public class Entite implements Serializable {
static final long serialVersionUID = 3L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int entiteId;
private String entiteName;
private String affectation, Wilayas, type, Mougattaa;
// @JsonBackReference
@OneToMany(mappedBy = "entite", fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
@JsonIgnore
// @JoinTable(name = "dep_ent_TABLE",
// joinColumns = @JoinColumn(name = "entite_id"),
// inverseJoinColumns = @JoinColumn(name = "department_id")
// )
// ( cascade = CascadeType.REMOVE)
private Set<Department> departments;
// private Department department;
protected Entite() {
departments = new HashSet<>();
}
}

另一类是

public class Department {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int departmentId;
@Column(name = "department_name")
private String departmentName;
@Column(name = "department_url")
private String departmentUrl;
@Column(name = "department_titre")
private String departmentTitre;
// @OneToMany(mappedBy = "department", cascade = CascadeType.REMOVE)
@ManyToOne
// @JsonIgnore
// @JsonManagedReference
private Entite entite;
public Department() {
// entites = new HashSet<>();
}
}

通过添加@JsonIgnore在代码的这一行之上

private Set<Department> departments;

让它发挥作用。

最新更新