Java Spring数据Rest/JPA级联在补丁上持久化
我有两个实体,Book和BookEvent。它们通过一种多对一关系联系在一起,即一本书可以有许多BookEvents。 我将Book视为聚合根目录,并为Book实体(而不是BookEvent)拥有一个存储库Java Spring数据Rest/JPA级联在补丁上持久化,java,jpa,spring-data-rest,Java,Jpa,Spring Data Rest,我有两个实体,Book和BookEvent。它们通过一种多对一关系联系在一起,即一本书可以有许多BookEvents。 我将Book视为聚合根目录,并为Book实体(而不是BookEvent)拥有一个存储库 @Entity @Table(name = "book") public class Book { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; priva
@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);
}
}
现在,我想在创建图书后向图书添加一个新事件。我使用Spring数据Rest
用一篇文章和一个事件创建一本书效果很好:
{
"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补丁来附加一个新事件,那么该事件将包含在对补丁请求的响应中,但它实际上不会保存在数据库中。之后,GET on the book不会返回该事件,并且当数据库中的book_id列为null时
[
{
"op": "add",
"path": "/events/-",
"value":
{
"date": "2017-05-09"
}
}
]
使用调试器时,在初始POST请求时调用setEvents方法,但在补丁请求期间,仅调用getEvents方法-无setBook或addEvent方法。我认为问题就在那里
我的实体设置有问题吗?问题是我的设置是双向的一个实体设置,没有联接表。问题可以通过两种方式解决: 创建联接表。这是通过向Book类的events属性添加@JoinTable注释来实现的。这需要在数据库中增加一个表,因此我没有选择这种方式。 使用单向OneToMany设置,请参见。这仅由JPA2.x支持,但在SpringBoot2.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
}
不需要更新交互链接的特殊getter/setter。这将获得一个带有SDR的干净JSON响应,每个事件上都没有_links属性。添加和删除新条目同样有效。man我已经做了与您类似的所有事情,但在持久化子实体时出错-它没有获取父实体的id
@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
}