场景描述
班级与学生一对多,一个班级中有多个学生,
我们只希望操作班级,而将学生的一些操作直接级联到数据库。
示例
实体
@Entity
public class Klass {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@OneToMany(mappedBy = "klass")
private Set<Student> studentSet = new HashSet<>();
}
@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String name;
@ManyToOne
private Klass klass;
}
不级联
@Test
public void test() {
Klass klass = new Klass();
klass.setName("测试班级");
Student student1 = new Student();
Student student2 = new Student();
student1.setName("测试学生1");
student2.setName("测试学生2");
klass.setStudentSet(new HashSet<>(Arrays.asList(student1, student2)));
klassRepository.save(klass);
}
班级表:
学生表:
PERSIST
@OneToMany(mappedBy = "klass", cascade = CascadeType.PERSIST)
private Set<Student> studentSet = new HashSet<>();
班级表:
学生表:
学生已经级联保存,但是学生的klass_id
却是空,可见级联是直接将set
中的对象持久化到数据库,而未对其ManyToOne
的关系进行维护。我们需要手动维护多对一的关系。
@Test
public void test() {
Klass klass = new Klass();
klass.setName("测试班级");
Student student1 = new Student();
Student student2 = new Student();
student1.setName("测试学生1");
student2.setName("测试学生2");
student1.setKlass(klass);
student2.setKlass(klass);
klass.setStudentSet(new HashSet<>(Arrays.asList(student1, student2)));
klassRepository.save(klass);
}
班级表:
学生表:
MERGE
@OneToMany(mappedBy = "klass", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
private Set<Student> studentSet = new HashSet<>();
官方文档:CascadeType.MERGE
@Test
public void test() {
Klass klass = klassRepository.findOne(1L);
for (Student student : klass.getStudentSet()) {
student.setName("修改后的学生");
}
klassRepository.save(klass);
}
During merge, the current state of the entity is copied onto the entity version that was just fetched from the database. That’s the reason why Hibernate executed the SELECT statement which fetched both the Person entity along with its children.在
MERGE
期间,实体的当前状态被复制到刚刚从数据库中取出的实体版本。这就是为什么Hibernate执行SELECT语句,既能获取Person
实体,又能获取它的子实体。
REMOVE
为OneToMany
的级联加上属性CascadeType.REMOVE
。
删除就简单了,我们直接测试删除掉id
为1
的班级,此时数据库设置为update
。
@Test
public void test() {
klassRepository.delete((long) 1);
}
班级表该条记录删除,同时学生表中的记录也被级联删除。