Spring 数据 JPA - findAll 没有 return 关系数据

Spring Data JPA - findAll does not return relations data

我有 2 个表 - 放映 (ManyToOne) 和房间 (OneToMany)。当我在房间存储库上使用 findAll 时,它 returns 我 json 带有放映数据,但是当我以相反的方式 (screenings.findAll) 这样做时,它不会 returns 房间。在模型筛选中,我有关系:

@ManyToOne
@JoinColumn(name = "room_id")
@JsonBackReference
private Room room;

在房间模型中:

@OneToMany(mappedBy="room")
@JsonManagedReference
private List<Screening> screenings;

筛选服务包含:

    @Autowired
    public ScreeningService(ScreeningRepository screeningRepository) {
        this.screeningRepository = screeningRepository;
    }

    public List<Screening> getScreenings(){
        return screeningRepository.findAll();
    }

并且返回值没有房间模型:

{
"id": 1,
"startDate": "2022-06-20T13:00:00.000+00:00",
"endDate": "2022-06-20T15:00:00.000+00:00"
},
{
"id": 2,
"startDate": "2022-06-20T13:15:00.000+00:00",
"endDate": "2022-06-20T15:15:00.000+00:00"
},

当我以相反的方式这样做并调用

public List<Room> getRooms() {
        return roomRepository.findAll();
    }

结果和我想要的一模一样:

{
"id": 2,
"number": 2,
"screenings": [
{
"id": 2,
"startDate": "2022-06-20T13:15:00.000+00:00",
"endDate": "2022-06-20T15:15:00.000+00:00"
},
{
"id": 5,
"startDate": "2022-06-20T13:15:00.000+00:00",
"endDate": "2022-06-20T15:15:00.000+00:00"
},
{
"id": 7,
"startDate": "2022-06-20T18:15:00.000+00:00",
"endDate": "2022-06-20T21:15:00.000+00:00"
}
]
},

这有可能做错或我做错了什么吗?

问题出在 JSON 序列化级别。

你们是双向关系!
如果您在默认情况下序列化这些对象而没有附加注释(@JsonManagedReference@JsonBackReference),您将得到 WhosebugError 异常。原因是Jackson通过双向关系陷入了无限递归。

因此,为了解决 Jackson JSON 无限递归问题,您使用了 @JsonManagedReference, @JsonBackReference。注释的主要思想是将关系分为两部分:父级和子级。
@JsonManagedReference 是引用的父(或“转发”)部分——正常序列化的部分。
@JsonBackReference 是引用的子(或“后”)部分——它将在序列化中被忽略。
所以杰克逊只会序列化一个关系部分,永远不会进入无限循环。你可以在你的例子中看到它。
或者,我们也可以使用 @JsonIgnore 注释来简单地忽略关系的一侧,从而打破链条。

如果您希望能够从两侧序列化对象:
解法:Annotation JsonIdentityInfo

Annotation used for indicating that values of annotated type or property should be serializing so that instances either contain additional object identifier (in addition actual object properties), or as a reference that consists of an object id that refers to a full serialization. In practice this is done by serializing the first instance as full object and object identity, and other references to the object as reference values.

从您的实体中删除 @JsonManagedReference@JsonBackReference 注释。

将 class 级别注释添加到 Screening 实体:

@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "id")
public class Screening { ... }

将 class 级别注释添加到 Room 实体:

@JsonIdentityInfo(
  generator = ObjectIdGenerators.PropertyGenerator.class, 
  property = "id")
public class Room { ... }

Room实体的输出:

{
  "id": 2,
  "number": 2,
  "screenings": [
    {
      "id": 2,
      "startDate": "2022-06-20T13:15:00.000+00:00",
      "endDate": "2022-06-20T15:15:00.000+00:00",
      "room": 2
    },
    {
      "id": 5,
      "startDate": "2022-06-20T13:15:00.000+00:00",
      "endDate": "2022-06-20T15:15:00.000+00:00",
      "room": 2
    },
    {
      "id": 7,
      "startDate": "2022-06-20T18:15:00.000+00:00",
      "endDate": "2022-06-20T21:15:00.000+00:00",
      "room": 2
    }
  ]
}

Screening实体的输出:

{
  "id": 2,
  "startDate": "2022-06-20T13:15:00.000+00:00",
  "endDate": "2022-06-20T15:15:00.000+00:00",
  "room": {
    "id": 2,
    "number": 2,
    "screenings": [2,5,7]
  }
}

如果 @JsonIdentityInfo 的默认行为不适合您的用例,您可以创建 Custom Serializer 并自行处理双向问题。