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
上使用 EntityManager
到 persist()
时,它会自动调用 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));
假设我有一对多关系:
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
上使用 EntityManager
到 persist()
时,它会自动调用 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));