【发布时间】:2018-03-07 14:45:22
【问题描述】:
根据这篇文章Difference between @OneToMany and @ElementCollection?,我更喜欢@ElementCollection 用于可嵌入类型,@OneToMany 用于实体。但是使用@OneToMany 我可以额外设置选项orphanRemoval=true。我怎样才能用@ElementCollection 做到这一点?它暗示了吗?
【问题讨论】:
根据这篇文章Difference between @OneToMany and @ElementCollection?,我更喜欢@ElementCollection 用于可嵌入类型,@OneToMany 用于实体。但是使用@OneToMany 我可以额外设置选项orphanRemoval=true。我怎样才能用@ElementCollection 做到这一点?它暗示了吗?
【问题讨论】:
这是隐含的。删除拥有实体也会删除@ElementCollection 上的所有数据。如果Session 尚未关闭,将Collection 设置为null 或更改Collection 中的元素将导致更新。
官方文档here是这样说的:
2.8.1。集合作为值类型
值和可嵌入类型集合具有类似的行为 简单的值类型,因为它们在 由持久对象引用并在发生时自动删除 未引用。如果一个集合从一个持久对象传递到 另一个,它的元素可能会从一个表移动到另一个表。
...
对于值类型的集合,JPA 2.0 定义了 @ElementCollection 注解。值类型集合的生命周期完全是 由其所属实体控制。
我运行了这三个测试来测试它:
@Test
public void selectStudentAndSetBooksCollectionToNull() {
Student student = studentDao.getById(3L);
List<String> books = student.getBooks();
books.forEach(System.out::println);
student.setBooks(null);
em.flush(); // delete from student_book where student_id = ?
}
@Test
public void selectStudentAndAddBookInCollection() {
Student student = studentDao.getById(3L);
List<String> books = student.getBooks();
books.add("PHP Book");
books.forEach(System.out::println);
em.flush(); // insert into student_book(student_id, book) values(?, ?)
}
@Test
public void selectStudentAndChangeCollection() {
Student student = studentDao.getById(3L);
List<String> newBooks = new ArrayList<>();
newBooks.add("Rocket Engineering");
newBooks.forEach(System.out::println);
student.setBooks(newBooks);
em.flush(); // delete from student_book where student_id = ?
// insert into student_book(student_id, book) values(?, ?)
}
这是Student 类:
@Entity
@Table(name = "student")
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "student_id", nullable = false, insertable = false, updatable = false)
private Long id;
@Column(name = "name", nullable = false)
private String name;
@ElementCollection
@CollectionTable(
name = "student_books",
joinColumns = @JoinColumn(name = "student_id", referencedColumnName = "student_id"))
@Column(name = "book")
private List<String> books = new ArrayList<>();
// Getters & Setters
}
【讨论】:
@ElementCollection 字段隐含了Cascasde.ALL + orphanRemoval = true