Spring Boot 与JPA/Hibernate和Jackson的循环依赖关系[重复]

3zwtqj6y  于 2022-11-23  发布在  Spring
关注(0)|答案(1)|浏览(147)

此问题在此处已有答案

Infinite Recursion with Jackson JSON and Hibernate JPA issue(28个答案)
7天前关闭。
我有一个Sping Boot 应用程序,在其持久层中使用JPA/Hibernate,该应用程序对数据库具有只读访问权限,基本上有三个实体ArticleCategoryField,它们具有以下关系。

Article (*) -> (1) Category (*) <-> (1) Field

也就是说,一个Article有一个Category,一个Category总是属于一个Field,但是,多个Category示例可以属于同一个Field
应用程序提供了两个REST端点,它们通过ID分别给予了一个Article和一个Field。当然,由于Category <-> Field的循环依赖关系,在使用Jackson进行序列化时,这是行不通的。
我想要的是当我检索一个Article时,它应该给予我它的Category,包括类别的Field,但不是属于同一个Field的所有其他Category示例。另一方面,当我检索一个Field时,它应该给予Field,其中包括属于此Field的所有Category示例。
我如何才能做到这一点?
编辑:我基本上有一个与Jackson infinite loops many-to-one one-to-many relation类似的问题

svmlkihl

svmlkihl1#

您可以使用基于接口的投影来仅检索所需的属性,因为SpringData允许对专用返回类型进行建模,从而更有选择性地检索托管聚合的部分视图。
让我们假设实体的声明如下所示,为了简单起见,只定义了id属性和关联Map属性。
第一个
对于Article由id获取的第一个端点,应如下声明投影:

public interface ArticleDto {
    Long getId();
    CategoryDto1 getCategory();

    interface CategoryDto1 {
      Long getId();
      FieldDto1 getField();
    }

    interface FieldDto1 {
      Long getId();
    }
 }

这里重要的一点是,这里定义的属性与聚合根中的属性完全匹配。
然后,在ArticleRepository中定义附加查询方法:

interface ArticleRepository extends JpaRepository<Article, Long> {
    Optional<ArticleDto> findDtoById(Long id);
}

查询执行引擎在运行时为返回的每个元素创建该接口的代理示例,并将对公开方法的调用转发给目标对象。
声明其他投影以检索第二种情况所需的属性:

public interface FieldDto2 {
    Long getId();
    Set<CategoryDto2> getCategories();

    interface CategoryDto2 {
      Long getId();
    }
}

最后,在FieldRepository中定义以下查询方法:

interface FieldRepository extends JpaRepository<Field, Long> {
    Optional<FieldDto2> findDtoById(Long id);
}

使用这种方法,只要投影不包含导致递归的属性,就不会出现无限递归异常。

相关问题