小编典典

REST控制器中具有一对多关系的实体的递归JSON视图

java

我正在使用SpringBoot和JPA构建REST接口。

现在,对于从数据库中获取的产品列表,我返回了一个奇怪的JSON。假设我有:

@Entity
public class Product {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @ManyToOne(optional = false, fetch = FetchType.LAZY)
    @JoinColumn(name = "categoryId", nullable = false, updatable = false)
    private Category category;

    ...
}

@Entity
public class Category implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @OneToMany(mappedBy = "category", cascade = CascadeType.DETACH)
    @OrderBy("name ASC")
    private List<Product> products = Collections.emptyList();

    ...
}

的JPA存储库Product定义为:

public interface ProductRepository extends JpaRepository<Product, Long> {
    List<Product> findAll();
}

在我的控制器中,我有:

@Autowired
private ProductRepository productRepo;

@RequestMapping("/all-products", method = RequestMethod.GET)
public Map<String,Object> home() {
    Map<String,Object> model = new HashMap<String,Object>();
    model.put("products", productRepo.findAll());
    return model;
}

使我发疯的是,如果我尝试按以下方式致电此服务:

$ curl localhost:8080/all-products

由于表product和之间的关系,我得到了递归输出category,例如:

{"products":[{"id":1,"name":"Product1","category":
{"id":1,"name":"Cat1","products":[{"id":6,"name":"Product6","category":
{"id":1,"name":"Cat1","products":[{"id":6,"name":"Product6","category":
{"id":1,...

我究竟做错了什么?


阅读 223

收藏
2020-11-13

共1个答案

小编典典

您没有做错任何事情(至少在代码级别上是概念上的)-json序列化器如下所示:

  1. 产品-对其进行序列化,但是请稍候-有一个类别字段,因此序列化程序必须对类别字段进行序列化
  2. 类别-对其进行序列化,但是请稍候-有一个product字段,因此序列化程序必须序列化列表中的每个产品
  3. 产品-由于您的收藏包含产品和产品包含类别,因此它会不断循环直到超时。

您必须使用视图或只是跳过它。

  1. @JsonView

  2. 将视图用作new ProductView具有产品的所有字段和对new CategoryView(您可以在此处结束)具有(产品)集合的引用(类别)的POJO Return ,new ProductViewWithoutReferences依此类推

  3. 用于@JsonIgnore一系列产品

另外请注意-
如果是,@RestController并且您正在调用“所有产品”,则返回除列表以外的其他内容有点不寻常。将响应包装在映射中是多余的。许多其他客户端在调用list()方法时都希望有一个列表。

2020-11-13