簡體   English   中英

Spring 數據 JPA - findAll 不返回關系數據

[英]Spring Data JPA - findAll does not return relations data

我有 2 個表 - 放映 (ManyToOne) 和房間 (OneToMany)。 當我在房間存儲庫上使用 findAll 時,它會返回一個帶有放映數據的 json,但是當我以相反的方式 (screenings.findAll) 執行此操作時,它不會返回房間。 在model篩選我有關系:

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

在 model 房間:

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

篩選服務包含:

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

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

並且返回值沒有房間 model:

{
"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 ),您將得到StackOverflowError異常。 原因是Jackson通過雙向關系進入無限遞歸。

因此,要解決 Jackson JSON 無限遞歸問題,您使用了 @JsonManagedReference@JsonBackReference 注釋的主要思想是將關系分為兩部分:父級和子級。
@JsonManagedReference是引用的父(或“轉發”)部分——正常序列化的部分。
@JsonBackReference是引用的子(或“后”)部分——它將從序列化中省略。
所以 Jackson 只會序列化一個關系部分,永遠不會進入無限循環。 你可以在你的例子中看到它。
或者,我們也可以使用@JsonIgnore注釋來簡單地忽略關系的一側,從而打破鏈條。

如果您希望能夠從兩側序列化對象:
解決方案: 注解JsonIdentityInfo

用於指示帶注釋的類型或屬性的值應該被序列化的注釋,以便實例包含額外的 object 標識符(除了實際的 object 屬性),或者作為包含引用完整序列化的 object id 的引用。 實際上,這是通過將第一個實例序列化為完整的 object 和 object 身份,以及對 object 的其他引用作為參考值來完成的。

從您的實體中刪除@JsonManagedReference@JsonBackReference注釋。

將 class 級別注釋添加到Screening實體:

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

Room實體添加 class 級別注解:

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

Room實體output:

{
  "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單位output:

{
  "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的默認行為不適合您的用例,您可以創建自定義序列化程序並自行處理雙向問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM