【问题标题】:ManyToMany Hibernate save related objectManyToMany Hibernate 保存相关对象
【发布时间】:2020-09-03 03:05:40
【问题描述】:

我正在学习 Spring JPA,我从将对象映射到表开始。我对 OneToOne 和 OneToMany 关系没有任何问题,但我不太明白为什么我无法保留与 ManyToMany 关系相关的对象。 我有一本可以有很多作者的书和一个可以有很多书的作者。 使用中间表 book_author 正确生成了模式(我可以在 MySql Workbench 中看到它),但我得到了这个例外:

Hibernate:插入作者(first_name,last_name)值(?,?)

休眠:插入书籍(种类,标题)值(?,?)

休眠:插入书籍(种类,标题)值(?,?)

Hibernate:插入 author_book (author_id, book_id) 值 (?, ?)

Hibernate:插入 author_book (author_id, book_id) 值 (?, ?)

Hibernate:插入作者(first_name,last_name)值(?,?)

线程“main”中的异常 org.springframework.dao.InvalidDataAccessApiUsageException:分离的实体传递给持久化:com.example.demo.models.Book;嵌套异常是 org.hibernate.PersistentObjectException:分离的实体传递给持久化:com.example.demo.models.Book

我还粘贴了可以正常运行的 Hibernate 操作。

这些是我的实体定义:

@Table(name = "author")
public class Author {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    private String firstName;
    private String lastName;

    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.ALL})
    @JoinTable(
            name = "author_book",
            joinColumns = {@JoinColumn(name = "author_id")},
            inverseJoinColumns = {@JoinColumn(name = "book_id")}
            )
    private List<Book> books = new ArrayList<Book>();

    //getters and setters omitted for brevity
}

@Entity(name = "Book")
@Table(name = "book")
public class Book {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Long id;
    private String title;
    private String kind;
    @ManyToMany(mappedBy = "books")
    private List<Author> authors = new ArrayList<Author>();

    //getters and setters omitted for brevity
}

这些是我的存储库:

@Repository
public interface AuthorRepository extends CrudRepository<Author, Long> {

}

@Repository
public interface BookRepository extends CrudRepository<Book, Long> {

}

最后这是我的主要内容

public static void main(String[] args) {
        ApplicationContext ctx = SpringApplication.run(DemoApplication.class, args);
        AuthorRepository authorRepository = ctx.getBean(AuthorRepository.class);
        BookRepository bookRepository = ctx.getBean(BookRepository.class);

        Author author = new Author();
        author.setFirstName("Author");
        author.setLastName("First");

        Author author2 = new Author();
        author.setFirstName("Author");
        author.setLastName("Second");

        Book book1 = new Book();
        book1.setTitle("Book 1");
        book1.setKind("History");
        book1.getAuthors().add(author);
        book1.getAuthors().add(author2);

        Book book2 = new Book();
        book2.setTitle("Book 2");
        book2.setKind("Science");
        book2.getAuthors().add(author);

        author.getBooks().add(book1);
        author.getBooks().add(book2);
        author2.getBooks().add(book1);

        authorRepository.save(author);
        authorRepository.save(author2);

        System.out.println("-->End of db operation");

    }

【问题讨论】:

    标签: java mysql spring hibernate jpa


    【解决方案1】:

    Author 类中创建一个新方法来添加book 而不是使用author.getBooks().add(book1)

        public void addBook(Book book) {
            books.add(book);
            books.authors.add(this);
        }
    

    而且你也不应该使用CascadeType.ALL,因为在删除实体时,关系的另一端也会被删除

    【讨论】:

      【解决方案2】:

      Hibernate 为一个对象维护 3 种状态:

      1. 瞬态:新创建的对象
      2. 持久化:当 Hibernate 保存对象时
      3. 已分离:保存对象并关闭会话后

      在您的情况下,authorRepository 保存瞬态对象(作者、book1 和 book2)并在保存后关闭会话。因此,所有对象(作者、book1 和 book2)在第一次调用 save 方法后都处于分离状态,这就是当您尝试保存 author2 时,Hibernate 抛出分离实体异常的原因。您可以在此视频中找到更多信息 https://www.youtube.com/watch?v=sjZGFHEdD4M&list=PL4AFF701184976B25&index=25

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-03-31
        • 1970-01-01
        • 2015-02-15
        • 2010-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多