我正在尝试使用Spring创建 REST 服务。 一切正常,直到我尝试将对象列表(CartItem)添加到我的主对象(Cart)中。
这是我的主要对象
@Entity
@Table(name="cart")
public class Cart implements Serializable{
...
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
@Column(name="id")
private Integer id;
/*when I add this I get the error. If I remove this, the
REST service works*/
@OneToMany(mappedBy="cart", fetch = FetchType.EAGER)
private List<CartItem> cartItems;
//getter, setter, constructors, other fields ecc.
}
这是列表中的对象:
@Entity
@Table(name="cart_item")
public class CartItem implements Serializable{
...
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
@Column(name="id")
private Integer id;
@OneToOne(targetEntity = Product.class, cascade = CascadeType.ALL)
@JoinColumn(referencedColumnName="productId", name="product_id" )
private Product product;
@ManyToOne
@JoinColumn(name="cart_id", nullable=false)
private Cart cart;
//getter, setter, constructors, other fields ecc.
}
这是我的控制人
@RestController
@RequestMapping(value="rest/cart")
public class CartRestController {
...
@RequestMapping(value = "/", method = RequestMethod.GET)
public List<Cart> readAll() {
return cartService.read();
}
...
}
我收到此错误:
SEVERE: Servlet.service() for servlet [dispatcher] in context with path
[/webstore] threw exception [Request processing failed; nested exception
is org.springframework.http.converter.HttpMessageNotWritableException:
Could not write JSON: Infinite recursion (StackOverflowError); nested
exception is com.fasterxml.jackson.databind.JsonMappingException:
Infinite recursion (StackOverflowError) (through reference chain:...
我想我必须以一种特殊的方式来管理Cart对象内的List,也许是因为我使用的是JPA,但我仍然没有在Internet上找到解决方案。 谁能帮我吗?
答案 0 :(得分:2)
这是序列化递归问题,因为CartItem具有回溯到Cart的双向映射而发生。
您可能希望通过使用@JsonIgnore
批注将CartItem.cart字段从序列化中排除。
如果直接在Web服务内部使用JPA实体,那么将太多的信息暴露给外界很容易。杰克逊实际上有一个称为JsonView的有用功能,它允许您定义要公开的属性,甚至可以根据需要针对每个Web服务调用对其进行定制。
答案 1 :(得分:1)
永远不会结束列表?您是说stackOverFlow异常吗?
如果情况就像我说的那样,那么您应该检查诸如访存类型和实体的toString()或equal()方法之类的东西。
例如,存在一个名为A和B的实体,它们之间的关系是一对多(A是一个)。如果将两个fetchType都配置为Eager,则当jpa查询A时,它也会查询B。但是B也包含A,因此jpa会再次查询A。这种循环会导致stackOverFlow。
顺便说一句,如何提供有关您的问题的更多信息(例如“异常”名称)?我很难为您提供具体的解决方案,我所能做的就是告诉您我以前见过的一些经验。
好吧,我用SpringBoot 2.1.0和MySql创建了一个小项目。
这是我的购物车
public class CartItem {
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id
@Column(name="id")
private Integer id;
@JsonIgnore
@ManyToOne
@JoinColumn(name="cart_id", nullable=false)
private Cart cart;
}
和我的购物车:
public class Cart {
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Id
@Column(name="id")
private Integer id;
@OneToMany(mappedBy="cart", fetch = FetchType.EAGER)
private List<CartItem> cartItems;
}
控制器与您编写的相同。在CartItem的购物车文件中添加@JsonIgnore之后,循环循环结束(在执行此操作之前,程序确实出现了循环循环问题)。
每次将jpa与@ oneToMany,@ ManyToOne或@ManyToMany一起使用时,都应谨慎对待此问题。实例化对象,打印对象或类似对象时可能会发生这种循环引用情况。有很多解决方法,例如将获取类型更改为LAZY,添加@JsonIgnore,覆盖toString()和equal()方法。