简体   繁体   中英

Hibernate throws EntityNotFoundException when fire merge of a one-to-many relationship

I'm using spring-data-jpa 2.1.3 with hibernate-core 5.3.7, and I have a bidirectional one-to-many relationship, when saving a child entity with existing parent entity EntityNotFoundException throws.

I have two entity Book and BookCategory, one BookCategory has multiple Books, see my entity below:

@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(){}
}

And then I try to save a Book with an existing BookCategory like this:

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);

Then EntityNotFoundException throws saying could't find Book with id "my book" when loading BookCategory while fire merge, however this is exatcly what I want to store in database. see 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]

However this could work on jpa 1.x and Hibernate 5.0, meanwhile if I remove this code in Book constructor : this.bookCategory.getBooks().add(this); to not add book back in bookCategory then everything works fine, I can save the Book.

Maybe does anyone know what's the issue?

Insert the Book first then update it with the reference of BookCategory . The code will looks like

@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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM