Jackson 在中间 table 上的无限递归
Infinite recursion with Jackson on intermediate table
我正在使用 Spring Boot、Jackson 和 Hibernate 创建一个 API。 Hibernate 连接到 MySQL 数据库。
我了解良好做法,但我坚持一个特定的观点。
我有一个包含额外字段的 n:m 关系。
例如:作者(id, ...) -> 书面(idAuthor, idBook, 日期) <- 书(id, ...)
我了解如何映射传统的 n:m 关系,但这次该技术不适用于我。
为此,我在互联网上找到了一个显示解决方案的来源:在我的代码中创建一个中间体 class,其中包含作者类型对象和书籍类型对象 + 我的附加字段。
@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 ....
}
这是双向的 link。
使用此代码,我得到一个无限递归错误:
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (WhosebugError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (WhosebugError) (through reference chain: java.util.ArrayList[0]->com.exampleAPI.api.model.Book["written"])]
我尝试在 Written class 上使用 @JsonIgnore
、@JsonManagedReference
和 @JsonBackReference
,也尝试使用 transient
关键字,但没有任何效果。
我在 Internet 上找不到任何可以帮助我的资源,也找不到针对此特定案例的文档。
有人可以帮助我吗?
当出现未处理的双向关系时,杰克逊面临无限递归。
I tried to use @JsonIgnore, @JsonManagedReference and @JsonBackReference on the Written class
您需要使用 @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, however ModelMapper 也是一个选项。如果此类实体的数量较少,则使用 constructors/getters/setters 就足够了。
我正在使用 Spring Boot、Jackson 和 Hibernate 创建一个 API。 Hibernate 连接到 MySQL 数据库。 我了解良好做法,但我坚持一个特定的观点。 我有一个包含额外字段的 n:m 关系。
例如:作者(id, ...) -> 书面(idAuthor, idBook, 日期) <- 书(id, ...)
我了解如何映射传统的 n:m 关系,但这次该技术不适用于我。
为此,我在互联网上找到了一个显示解决方案的来源:在我的代码中创建一个中间体 class,其中包含作者类型对象和书籍类型对象 + 我的附加字段。
@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 ....
}
这是双向的 link。 使用此代码,我得到一个无限递归错误:
Resolved [org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (WhosebugError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (WhosebugError) (through reference chain: java.util.ArrayList[0]->com.exampleAPI.api.model.Book["written"])]
我尝试在 Written class 上使用 @JsonIgnore
、@JsonManagedReference
和 @JsonBackReference
,也尝试使用 transient
关键字,但没有任何效果。
我在 Internet 上找不到任何可以帮助我的资源,也找不到针对此特定案例的文档。
有人可以帮助我吗?
当出现未处理的双向关系时,杰克逊面临无限递归。
I tried to use @JsonIgnore, @JsonManagedReference and @JsonBackReference on the Written class
您需要使用 @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, however ModelMapper 也是一个选项。如果此类实体的数量较少,则使用 constructors/getters/setters 就足够了。