![](/img/trans.png)
[英]Spring Data JPA findAll() or findbyId() return wrong value in spring boot
[英]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.