java - 当一对多关系的火合并时,Hibernate 抛出 EntityNotFoundException

标签 java hibernate spring-boot jpa

我使用 spring-data-jpa 2.1.3 和 hibernate-core 5.3.7,并且在保存具有现有父实体的子实体时,我有双向一对多关系 EntityNotFoundException 抛出。

我有两个实体 Book 和 BookCategory,一个 BookCategory 有多个 Book,请参阅下面的实体:

@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 为“我的书”的书,但这正是我想要存储在数据库中的内容。查看堆栈跟踪:

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,然后使用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);

关于java - 当一对多关系的火合并时,Hibernate 抛出 EntityNotFoundException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57520003/

相关文章:

java - 我无法在 Eclipse 中重命名应用程序包名称

java - 线程 "main"java.lang.ClassCastException : [Ljava. lang.Object 中的异常;不能转换为 model.AdminPopulate

postgresql - 减少对包含实体的 JPQL POJO 的查询次数

mysql - 如何使用 MySQL 配置 Spring Cloud Zipkin Server 以实现持久化?

java - Spring Cloud 契约(Contract) : Write Contract Test for multiple consumer with different or partially different expectations

java - @TransactionalEventListener 在@EventListener 像相同上下文的魅力一样工作的地方不起作用

java - 如何查看我有多少抽奖结果并显示它?

java - 使用 ajax get 发送数据时出现错误

java - tomcat shutdown内存泄漏,java线程无法停止

java - org.hibernate.HibernateException : Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set