1

场景描述

班级与学生一对多,一个班级中有多个学生,

clipboard.png

我们只希望操作班级,而将学生的一些操作直接级联到数据库。

示例

实体

@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);
}

班级表:

clipboard.png

学生表:

clipboard.png

PERSIST

@OneToMany(mappedBy = "klass", cascade = CascadeType.PERSIST)
private Set<Student> studentSet = new HashSet<>();

班级表:

clipboard.png

学生表:

clipboard.png

学生已经级联保存,但是学生的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);
}

班级表:

clipboard.png

学生表:

clipboard.png

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);
}

clipboard.png

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

删除就简单了,我们直接测试删除掉id1的班级,此时数据库设置为update

@Test
public void test() {
    klassRepository.delete((long) 1);
}

clipboard.png

clipboard.png

班级表该条记录删除,同时学生表中的记录也被级联删除。


张喜硕
2.1k 声望423 粉丝

浅梦辄止,书墨未浓。


引用和评论

0 条评论