JPA 框架是否自动保存一对多关系?

Does JPA framework save One-To-Many relationship automatically?

假设我有一对多关系:

import javax.persistence.*;
import java.io.Serializable;
import java.util.Set;

@Entity
@Table(name = "books")
public class Book implements Serializable {

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

    private String title;
    private String author;
    @Column(unique = true)
    private String isbn;

    @OneToMany(mappedBy = "book", fetch = FetchType.LAZY,
            cascade = CascadeType.ALL)
    private Set<Page> pages;

    public Book() {
    }

    public Book(String title, String author, String isbn) {
        this.title = title;
        this.author = author;
        this.isbn = isbn;
    }

    // getters and setters, equals(), toString() .... (omitted for brevity)
}

import javax.persistence.*;
import java.io.Serializable;

@Entity
@Table(name = "pages")
public class Page implements Serializable {

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

    private int number;
    private String content;
    private String chapter;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "book_id", nullable = false)
    private Book book;

    public Page() {
    }

    public Page(int number, String content, String chapter, Book book) {
        this.number = number;
        this.content = content;
        this.chapter = chapter;
        this.book = book;
    }

    // getters and setters, equals(), toString() .... (omitted for brevity)
}

并将其存储在:

// create a new book
Book book = new Book("Java 101", "John Doe", "123456");
    
// save the book
bookRepository.save(book);
    
// create and save new pages
pageRepository.save(new Page(1, "Introduction contents", "Introduction", book));
pageRepository.save(new Page(65, "Java 8 contents", "Java 8", book));
pageRepository.save(new Page(95, "Concurrency contents", "Concurrency", book));

问题是:我真的需要手动 save 每个页面吗?我可以只使用 java 集合,然后只保存主要实体,如:

book.pages.add(new Page(1, "Introduction contents", "Introduction", book));

book.pages.add(new Page(65, "Java 8 contents", "Java 8", book));

book.pages.add(new Page(95, "Concurrency contents", "Concurrency", book));

bookRepository.save(book);

例子取自https://attacomsian.com/blog/spring-data-jpa-one-to-many-mapping

我想知道保存关系的正确和最佳方式,这就是为什么我在这里问而不是自己试验的原因,因为这篇文章似乎误导了很多人

这就是 Book#pages 上的 cascade 发挥作用的地方。当你将它配置为 CascadeType.ALL 时,这意味着当你在 Book 上使用 EntityManagerpersist() 时,它会自动调用 persist() 它的所有 Page.

禁用 cascade 后,您必须调用以下命令来保存新的 Book 及其所有页面:

entityManager.persist(book);
entityManager.persist(page1);
entityManager.persist(page2);
....
entityManager.persist(pageN);

但启用 cascade 后,您只需调用以下命令,因为 Page 上的所有 persist() 将自动级联调用。

entityManager.persist(book);

由于 spring-data-jpa 存储库在内部只使用相同的 EntityManager 来保存同一事务的对象,如果需要,您只需调用以下命令来保存书籍及其页面cascade 已启用:

Book book = new Book("Java 101", "John Doe", "123456");
book.pages.add(new Page(1, "Introduction contents", "Introduction", book));
book.pages.add(new Page(65, "Java 8 contents", "Java 8", book));
book.pages.add(new Page(95, "Concurrency contents", "Concurrency", book));
bookRepository.save(book);

否则,如果 cascade 被禁用,您必须调用以下命令来保存 Book 及其页面:

Book book = new Book("Java 101", "John Doe", "123456");
bookRepository.save(book);

pageRepository.save(new Page(1, "Introduction contents", "Introduction", book));
pageRepository.save(new Page(65, "Java 8 contents", "Java 8", book));
pageRepository.save(new Page(95, "Concurrency contents", "Concurrency", book));