JPA Hibernate 多对多 IllegalStateException
JPA Hibernate many to many IllegalStateException
我正在尝试创建多对多关系。我有一个 table 'library_branch',我想加入包含 'bookId'、'branchId' 和 'noOfCopies' 的 'BookCopies'。我有一个错误 ErrorMvcAutoConfiguration$StaticView
。我不确定我在哪里导致这种无限递归,任何帮助将不胜感激。
2021-11-26 14:54:43.544 ERROR 22348 --- [nio-8080-exec-1] s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/api/branch] and exception [Could not write JSON: Infinite recursion (WhosebugError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (WhosebugError) (through reference chain: com.example.demo.branch.Branch["inventory"]->org.hibernate.collection.internal.PersistentSet[0]->com.example.demo.inventory.Inventory["branch"]->com.example.demo.branch.Branch["inventory"]
InventoryId.java
package com.example.demo.inventory;
...
@Data @AllArgsConstructor
@NoArgsConstructor
@Embeddable
public class InventoryId implements Serializable {
@Column(name = "book_id")
private int bookId;
@Column(name = "branch_id")
private int branchId;
}
Inventory.java
package com.example.demo.inventory;
...
@Entity(name="Inventory")
@Table(name = "tblBookCopies")
public class Inventory {
@EmbeddedId
private InventoryId id;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("branch_id")
private Branch branch;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("book_id")
private Book book;
@Column(name="no_of_copies")
private int qty;
public Inventory( Branch branch, Book book, int qty) {
this.id = new InventoryId(branch.getId(),book.getId());
this.branch = branch;
this.book = book;
this.qty = qty;
}
...
}
Branch.java
package com.example.demo.branch;
...
@Entity(name="Branch")
@Table(name="tblLibraryBranch")
public class Branch {
@Id
@Column(name="id")
private int id;
@Column(name="name")
private String name;
@Column(name="address")
private String address;
@OneToMany(mappedBy = "branch", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Inventory> inventory = new HashSet<>();
...
}
问题是您的 Inventory
指向 Branch
而您的 Branch
引用了 Inventory
。问题出在杰克逊身上,你需要解释一下如何遵循这些形成循环依赖的引用。
选项 1)
不要使用实体进行序列化。通常您不想公开数据库实体 - 这些应该是内部对象。如果将它们映射到某个 DTO 表示并序列化,问题就会消失。
选项 2)
向 Jackson 解释如何遵循这些参考资料 - 您需要查看 JsonManagedReference
and JsonBackReference
。
在你的情况下你需要尝试类似的东西(但也要检查这个 blogpost 中的数字 7):
@Entity(name="Inventory")
@Table(name = "tblBookCopies")
public class Inventory {
...
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("branch_id")
@JsonManagedReference // <-------- THIS
private Branch branch;
...
}
和
@Entity(name="Branch")
@Table(name="tblLibraryBranch")
public class Branch {
...
@OneToMany(mappedBy = "branch", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonBackReference // <--------- THIS
private Set<Inventory> inventory = new HashSet<>();
...
}
我正在尝试创建多对多关系。我有一个 table 'library_branch',我想加入包含 'bookId'、'branchId' 和 'noOfCopies' 的 'BookCopies'。我有一个错误 ErrorMvcAutoConfiguration$StaticView
。我不确定我在哪里导致这种无限递归,任何帮助将不胜感激。
2021-11-26 14:54:43.544 ERROR 22348 --- [nio-8080-exec-1] s.e.ErrorMvcAutoConfiguration$StaticView : Cannot render error page for request [/api/branch] and exception [Could not write JSON: Infinite recursion (WhosebugError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (WhosebugError) (through reference chain: com.example.demo.branch.Branch["inventory"]->org.hibernate.collection.internal.PersistentSet[0]->com.example.demo.inventory.Inventory["branch"]->com.example.demo.branch.Branch["inventory"]
InventoryId.java
package com.example.demo.inventory;
...
@Data @AllArgsConstructor
@NoArgsConstructor
@Embeddable
public class InventoryId implements Serializable {
@Column(name = "book_id")
private int bookId;
@Column(name = "branch_id")
private int branchId;
}
Inventory.java
package com.example.demo.inventory;
...
@Entity(name="Inventory")
@Table(name = "tblBookCopies")
public class Inventory {
@EmbeddedId
private InventoryId id;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("branch_id")
private Branch branch;
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("book_id")
private Book book;
@Column(name="no_of_copies")
private int qty;
public Inventory( Branch branch, Book book, int qty) {
this.id = new InventoryId(branch.getId(),book.getId());
this.branch = branch;
this.book = book;
this.qty = qty;
}
...
}
Branch.java
package com.example.demo.branch;
...
@Entity(name="Branch")
@Table(name="tblLibraryBranch")
public class Branch {
@Id
@Column(name="id")
private int id;
@Column(name="name")
private String name;
@Column(name="address")
private String address;
@OneToMany(mappedBy = "branch", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<Inventory> inventory = new HashSet<>();
...
}
问题是您的 Inventory
指向 Branch
而您的 Branch
引用了 Inventory
。问题出在杰克逊身上,你需要解释一下如何遵循这些形成循环依赖的引用。
选项 1)
不要使用实体进行序列化。通常您不想公开数据库实体 - 这些应该是内部对象。如果将它们映射到某个 DTO 表示并序列化,问题就会消失。
选项 2)
向 Jackson 解释如何遵循这些参考资料 - 您需要查看 JsonManagedReference
and JsonBackReference
。
在你的情况下你需要尝试类似的东西(但也要检查这个 blogpost 中的数字 7):
@Entity(name="Inventory")
@Table(name = "tblBookCopies")
public class Inventory {
...
@ManyToOne(fetch = FetchType.LAZY)
@MapsId("branch_id")
@JsonManagedReference // <-------- THIS
private Branch branch;
...
}
和
@Entity(name="Branch")
@Table(name="tblLibraryBranch")
public class Branch {
...
@OneToMany(mappedBy = "branch", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonBackReference // <--------- THIS
private Set<Inventory> inventory = new HashSet<>();
...
}