我有两个实体Book
和BookEvent
。它们由ManyToOne-Relationship链接,即一本书可以有许多BookEvents。
我将Book视为聚合根,并为Book实体设置了一个Repository,但没有为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);
}
}
(这里省略了其他的getter / setter)。
@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请求的响应中,但它实际上并未保存在数据库中(之后的书上的GET不会返回事件当数据库的列book_id为空时。)
[
{
"op": "add",
"path": "/events/-",
"value":
{
"date": "2017-05-09"
}
}
]
使用调试器时,在初始POST请求中调用setEvents()
方法,但在PATCH请求期间,仅调用getEvents()
方法 - no setBook()
或{{1 }} 方法。我认为存在问题。
我的实体设置有问题吗?
答案 0 :(得分:1)
问题是我的设置是没有连接表的双向OneToMany设置。问题可以通过两种方式解决:
- "5432:5432"
注释来完成的。这需要在数据库中添加一个表,因此我没有选择这种方式。我的代码现在看起来如下:
@JoinTable
没有必要更新互惠链接的特殊getter / setter。这将获得带有SDR的干净JSON响应,而每个事件都没有@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
}
属性。添加和删除新条目也很有效。