cascade理解起来比较简单就是级联操作(增删改),inverse不是很好理解网上查的资料都是说维护关系用的,这个单词的意思是inverse是“逆,对面的”也就是反过来,inverse=true就是另一方维护的意思,反之就是自己维护,不知道有木有理解错误。。。。网上所说的维护关系,就是维护外键的值。
举个例子吧,有两张表:学校表school和学生表student,一对多的关系,代码和配置文件如下:
public class Student implements Serializable {
private String id;
private String name;
private School school;
}
<many-to-one name="school" class="com.bean.School" fetch="join"> <column name="SCHOOL_ID" /> </many-to-one>
public class School {
private String id;
private String name;
private Set<Student> students = new HashSet<Student>(0);
//添加学生
public void addStudent(Student s){
students.add(s);
}
}
//inverse="true"说明让另一方(即STUDENT)来维护STUDENT表中的外键,注意这里的inverse是指Scho//ol,因为这个是School表,这就意味着school不是主控方(主控方才会维护外键关系),不会维护STUDENT表的SCHOOL_ID字段 <set name="students" table="STUDENT" inverse="true" lazy="true" cascade="all-delete-orphan"> <key> <column name="SCHOOL_ID" /> </key> <one-to-many class="com.bean.Student" /> </set>
测试代码如下:
School school = new School();
school.setName("某某高校");
Student s1= new Student();
s1.setName("学生1");
school.addStudent(s1);
Student s2= new Student();
s2.setName("学生2");
school.addStudent(s2);
session.save(school);
运行结果:
Hibernate: insert into SCHOOL (NAME, ID) values (?, ?)
Hibernate: insert into STUDENT (NAME, SCHOOL_ID, ID) values (?, ?, ?)
Hibernate: insert into STUDENT (NAME, SCHOOL_ID, ID) values (?, ?, ?)
发送了3条SQL,再来看看数据库STUDENT表的记录
SCHOOL_ID 没有值,因为外键关系school已经不管了,需要student维护,修改测试代码:
School school = new School(); school.setName("某某高校"); Student s1= new Student(); s1.setName("学生1"); school.addStudent(s1); Student s2= new Student(); s2.setName("学生2"); school.addStudent(s2); s1.setSchool(school); s2.setSchool(school); session.save(school);
运行结果:
Hibernate: insert into SCHOOL (NAME, ID) values (?, ?)
Hibernate: insert into STUDENT (NAME, SCHOOL_ID, ID) values (?, ?, ?)
Hibernate: insert into STUDENT (NAME, SCHOOL_ID, ID) values (?, ?, ?)
也是发送了3条SQL,再来看看数据库STUDENT表的记录
结果说明设置inverse=“true”需要student执行setSchool方法来自己维护外键的关系,如果想让school来维护外键关系,则需要设置inverse=“false”,配置文件如下:
<set name="students" table="STUDENT" inverse="false" lazy="true" cascade="all-delete-orphan">
<key>
<column name="SCHOOL_ID" />
</key>
<one-to-many class="com.bean.Student" />
</set>
测试代码:
School school = new School();
school.setName("某某高校");
Student s1= new Student();
s1.setName("学生1");
school.addStudent(s1);
Student s2= new Student();
s2.setName("学生2");
school.addStudent(s2);
//s1.setSchool(school);
//s2.setSchool(school);
session.save(school);
运行结果:
Hibernate: insert into SCHOOL (NAME, ID) values (?, ?)
Hibernate: insert into STUDENT (NAME, SCHOOL_ID, ID) values (?, ?, ?)
Hibernate: insert into STUDENT (NAME, SCHOOL_ID, ID) values (?, ?, ?)
Hibernate: update STUDENT set SCHOOL_ID=? where ID=?
Hibernate: update STUDENT set SCHOOL_ID=? where ID=?
额外执行了两次update,说明school维护了外键关系,两次update就是更新外键的,在看看数据库student表:
cascade有四种取值:
none: 默认值,任何情况都不进行关联操作。
save-update: 在执行save/update/saveOrUpdate时进行关联操作。
delete: 在执行delete 时进行关联操作。
all: 所有情况下均进行关联操作,即save-update和delete。
all-delete-orphan: 当一个节点成为孤儿节点时,删除该节点。
这里说明一下设置cascade="all-delete-orphan",就是在执行
school.getStudents().remove(student);
student.setSchool(null);
student就成了孤儿节点了,那么hibernate在同步缓存到数据库时就会把对应的记录删除了。
ps:orphan就是孤儿的意思,英语不好伤不起。。。