如何将@RestController (Spring) 与对象的子列表一起使用

How to use @RestController (Spring) with a child List of object

我正在尝试使用 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 (WhosebugError); nested
 exception is com.fasterxml.jackson.databind.JsonMappingException: 
Infinite recursion (WhosebugError) (through reference chain:...

我想我必须以特定方式管理 Cart 对象中的 List,可能是因为我使用的是 JPA,但我仍然没有在 Internet 上找到解决方案。 谁能帮帮我?

永无止境的清单?您是指 Whosebug 异常吗?

如果情况就像我说的那样,那么你应该检查一些东西,比如获取类型和实体的 toString() 或 equal() 方法或类似的东西。

比如有实体A和B,它们是一对多的关系(A就是一个),如果你把它们的fetchType都配置为Eager,那么jpa查询A的时候,就会查询B too.But B也包含A,所以jpa会查询A again.This 那种循环会导致Whosebug。

顺便问一下,能否提供更多关于你的问题的信息,比如异常名称?我很难给你一个具体的解决方案,我只能告诉你一些我以前遇到的经验。


嗯,我用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;
}

Controller和你一样wrote.After在CartItem的cart filed中添加了一个@JsonIgnore,循环结束(在我这样做之前,程序确实有一个循环问题)。

每次在@oneToMany、@ManyToOne 或@ManyToMany 中使用 jpa 时,您都应该注意这种 problem.This 在实例化对象、打印对象或类似 this.And 当然有很多方法可以解决它,比如将获取类型更改为 LAZY,添加 @JsonIgnore,重写 toString() 和 equal() 方法。

这是一个序列化递归问题,它的发生是因为CartItem 有一个双向映射回Cart。所以发生的是

  • 购物车序列化为 JSON
    • 其中的所有 CartItems 都序列化为 JSON
      • CartItem 中的购物车 属性 序列化为 JSON
        • 购物车内的 CartItems 序列化为 json,等等

您可能希望通过使用 @JsonIgnore 注释标记 CartItem.cart 字段来将其从序列化中排除。


如果您直接在 Web 服务中使用 JPA 实体,那么很容易向外界公开过多的信息。 Jackson 实际上有一个有用的功能,称为 ,它允许您定义公开哪些属性,如果需要,您甚至可以根据网络服务调用对其进行定制。