簡體   English   中英

Spring Data Rest / JPA級聯仍然存在於補丁程序中

[英]Spring Data Rest/JPA cascade persist on patch

我有兩個實體, BookBookEvent 它們通過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設置。 該問題可以通過兩種方式解決:

  • 創建一個聯接表。 這是通過在Book類的events屬性中添加@JoinTable批注來完成的。 這需要數據庫中另外一個表,因此我沒有選擇這種方式。
  • 使用單向OneToMany設置(請參閱Java Persistence / OneToMany )。 JPA 2.x僅支持此功能,但這在Spring Boot 2.0安裝程序中沒有問題。 這樣的實現看起來真的很干凈。

我的代碼現在如下所示:

@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.

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