中间表上杰克逊的无限递归
Posted
技术标签:
【中文标题】中间表上杰克逊的无限递归【英文标题】:Infinite recursion with Jackson on intermediate table 【发布时间】:2021-01-24 10:02:45 【问题描述】:我正在使用 Spring Boot、Jackson 和 Hibernate 创建 API。 Hibernate 连接到 mysql 数据库。 我理解好的做法,但我被困在一个特定的点上。 我有一个包含额外字段的 n:m 关系。
例如:作者(id, ...) -> 书面(idAuthor, idBook, date)
我了解如何映射传统的 n:m 关系,但这次我并不适用这种技术。
为此,我在互联网上找到了一个显示解决方案的来源:在我的代码中创建一个中间类,其中包含一个 Author 类型对象和一个 Book 类型对象 + 我的附加字段。
@Entity
@Table(name = "Author")
public class Author implements Serializable
/...
@Id
@GeneratedValue
private int id;
@OneToMany(mappedBy = "author", cascade = CascadeType.ALL)
private Set<Written> written= new HashSet<>();
/...
@Entity
@Table(name = "Book")
public class Book implements Serializable
/...
@Id
@GeneratedValue
private int id;
@OneToMany(mappedBy = "book", cascade = CascadeType.ALL)
private Set<Written> written= new HashSet<>();
/...
public class Written implements Serializable
@Id
@ManyToOne
@JoinColumn(name = "idAuthor")
private Author author;
@Id
@ManyToOne
@JoinColumn(name = "idBook")
private Book book;
//Extra fields ....
这是一个双向链接。 使用此代码,我得到一个无限递归错误:
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (***Error); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (***Error) (through reference chain: java.util.ArrayList[0]->com.exampleAPI.api.model.Book["written"])]
我尝试在 Written 类中使用 @JsonIgnore
、@JsonManagedReference
和 @JsonBackReference
,也尝试使用 transient
关键字,但没有任何效果。
我在互联网上找不到任何可以帮助我的资源,也找不到此特定案例的文档。
有人可以帮我吗?
【问题讨论】:
类似问题:Jackson serialize problem in @ManyToMany relationship, Jackson/Hibernate, meta get methods and serialization 【参考方案1】:当出现未处理的双向关系时,Jackson 面临无限递归。
我尝试在 Written 类中使用 @JsonIgnore、@JsonManagedReference 和 @JsonBackReference
您需要单独使用@JsonManagedReference
和@JsonBackReference
注释来防止Book
和Written
之间的这些循环。附带说明,transient
与持久性无关,而是与序列化有关。 JPA 使用 @Transient
注释。
public class Book implements Serializable
@OneToMany(mappedBy = "book", cascade = CascadeType.ALL)
@JsonBackReference
private Set<Written> written= new HashSet<>();
...
public class Written implements Serializable
@Id
@ManyToOne
@JoinColumn(name = "idBook")
@JsonManagedReference
private Book book;
...
重要提示:不要通过 REST 发送数据库实体(可能是您要做的)。更好地创建一个没有双向关系的 DAO 对象并将实体映射到 DAO。有几个库可以做到这一点:我强烈推荐MapStruct,但ModelMapper 也是一种选择。如果此类实体的数量较少,则使用构造函数/getter/setter 就足够了。
【讨论】:
哦,非常感谢,但繁殖行为并不完全符合预期。我现在可以检索书籍及其信息(不再有无限递归错误),但没有作者的踪迹或存储在 Written 中的其他字段。有什么建议吗? @nicooooo 使用映射库仅映射书籍的“第一”层,而无需进一步参考作者。 我提前道歉,但这是我在这个领域的第一个应用程序,我不知道该怎么做 没关系。为简单起见,除非您真的需要它们,否则不要使用双向关系。有关 entity-to-dto-mapping 的更多信息,请在 Google 上搜索此术语:MapStruct entity to dto,您会发现大量教程可供开始。以上是关于中间表上杰克逊的无限递归的主要内容,如果未能解决你的问题,请参考以下文章