[英]Spring Data Rest/JPA cascade persist on patch
我有兩個實體, Book
和BookEvent
。 它們通過ManyToOne-Relationship關系鏈接,即一本書可以有多個BookEvent。 我將Book視為聚合根,並為Book實體(但BookEvent)沒有一個存儲庫。
@Entity
@Table(name = "book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
@OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
private List<BookEvent> events = new ArrayList<>();
public List<BookEvent> getEvents() {
return events;
}
public void setEvents(List<BookEvent> events) {
for (BookEvent event: events) {
event.setBook(this);
}
this.events = events;
}
public void addEvent(BookEvent event) {
events.add(event);
event.setBook(this);
}
public void removeEvent(BookEvent event) {
events.remove(event);
event.setBook(null);
}
}
(此處省略了其他獲取器/設置器)。
@Entity
public class BookEvent {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@ManyToOne
@JoinColumn(name="book_id")
private Book book;
private LocalDate date;
@PreRemove
private void removeEventFromBook(){
book.removeEvent(this);
}
public Book getBook() {
return book;
}
public void setBook(Book book) {
this.book = book;
if (!this.book.getEvents().contains(this)) {
this.book.getEvents().add(this);
}
}
}
我現在想在創建書籍后向該書籍添加一個新事件。 我使用Spring Data Rest。
使用POST
和一個事件創建書可以正常工作:
{
"title": "My example book",
"events": [
{
"type": "BOUGHT",
"date": "2017-05-09"
}
]
}
給出答案:
{
"title": "My example book",
"events": [
{
"id": 3,
"date": "2017-05-09",
"_links": {
"book": {
"href": "http://localhost:8080/api/books/2"
}
}
}
]
}
但是,如果我隨后執行JSON Patch追加一個新事件,則該事件將包含在對PATCH請求的響應中,但實際上並未保存在數據庫中(此后的GET不會返回該事件,並且當數據庫列book_id為null)。
[
{
"op": "add",
"path": "/events/-",
"value":
{
"date": "2017-05-09"
}
}
]
使用調試器時,將在初始POST請求中調用setEvents()
方法,但是在PATCH請求期間,僅調用getEvents()
方法-不會setBook()
或addEvent()
方法。 我認為問題就在那里。
我的實體設置是否有問題?
問題是我的設置是沒有連接表的雙向OneToMany設置。 該問題可以通過兩種方式解決:
@JoinTable
批注來完成的。 這需要數據庫中另外一個表,因此我沒有選擇這種方式。 我的代碼現在如下所示:
@Entity
@Table(name = "book")
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = ALL) //The cascade is important as otherwise a new event won't be saved.
@JoinColumn(name="book_id", referencedColumnName = "id")
private List<BookEvent> events = new ArrayList<>();
//Standard getter and setter for getEvents() and setEvents()
}
@Entity
public class BookEvent {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name="book_id")
private Long bookId;
//No getter/setter for bookId was necessary
}
不需要用於更新相互鏈接的特殊獲取器/設置器。 這將獲得帶有SDR的干凈JSON響應,每個事件都沒有_links
屬性。 添加和刪除新條目也可以。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.