我将spring-data-jpa 2.1.3与hibernate-core 5.3.7结合使用,并且在保存具有现有父实体EntityNotFoundException
引发的子实体时,我具有双向的一对多关系。
我有两个实体Book和BookCategory,一个BookCategory有多个Books,请参见下面的我的实体:
@Data
@Entity
public class Book {
@Id
private String name;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE, targetEntity = BookCategory.class)
private BookCategory bookCategory;
public Book(){}
public Book(String name, BookCategory bookCategory){
this.name = name;
this.bookCategory = bookCategory;
this.bookCategory.getBooks().add(this);
}
}
@Data
@EqualsAndHashCode(exclude = "books")
@Entity
public class BookCategory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "bookCategory", targetEntity = Book.class)
private Set<Book> books;
public BookCategory(String name, Book... books) {
this.name = name;
}
public BookCategory(){}
}
然后,我尝试使用现有的BookCategory保存一本书,如下所示:
BookCategory bookCategory = bookCategoryRepository.findById(1).get();
Book book = new Book("my book",bookCategory); // this will set property both side, see in constructor
bookRepository.save(book);
然后
EntityNotFoundException
引发说,在火灾合并时加载BookCategory时找不到ID为“ my book”的Book,但这正是我要存储在数据库中的内容。参见stacktrace:Caused by: javax.persistence.EntityNotFoundException: Unable to find com.hellokoding.jpa.book.Book with id my book
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$JpaEntityNotFoundDelegate.handleEntityNotFound(EntityManagerFactoryBuilderImpl.java:162) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:230) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:281) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad(DefaultLoadEventListener.java:124) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:92) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1257) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1140) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:682) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:464) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.type.ManyToOneType.resolve(ManyToOneType.java:239) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.type.EntityType.resolve(EntityType.java:457) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.type.EntityType.replace(EntityType.java:358) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.type.CollectionType.replaceElements(CollectionType.java:551) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.type.CollectionType.replace(CollectionType.java:706) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.type.TypeHelper.replace(TypeHelper.java:163) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:393) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsPersistent(DefaultMergeEventListener.java:203) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:176) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:923) ~[hibernate-core-5.3.7.Final.jar:5.3.7.Final]
但是,这可以在jpa 1.x和Hibernate 5.0上运行,同时,如果我在Book构造函数中删除以下代码:
this.bookCategory.getBooks().add(this);
而不在bookCategory中添加回书,那么一切正常,我可以保存Book。也许有人知道出什么问题了吗?
最佳答案
首先插入Book
,然后用BookCategory
引用对其进行更新。该代码看起来像
@Data
@Entity
public class Book {
@Id
private String name;
@ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE, targetEntity = BookCategory.class)
private BookCategory bookCategory;
public Book(){}
public Book(String name) {
this.name = name;
}
public updateBookCategory(BookCategory bookCategory) {
this.bookCategory = bookCategory;
this.bookCategory.getBooks().add(this)
}
}
@Data
@EqualsAndHashCode(exclude = "books")
@Entity
public class BookCategory {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
private String name;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "bookCategory", targetEntity = Book.class)
private Set<Book> books;
public BookCategory(String name, Book... books) {
this.name = name;
}
public BookCategory(){}
}
BookCategory bookCategory = bookCategoryRepository.findById(1).get();
Book book = new Book("my book");
bookRepository.save(book);
book.updateBook(bookCategory);
bookRepository.merge(book);