inverse属性

    xiaoxiao2021-03-25  21

    前言

    查看这篇博客:https://www.mkyong.com/hibernate/inverse-true-example-and-explanation/ 作者的观点是inverse是”relationship_owner”,看完之后我也对一对多关系进行了测试发现蛮有道理的,但是等我用many-to-many测试的时候,就发现问题了,因为如果按照作者的观点如果是”relationship_owner”,那么我把两方的set的inverse都设置为true,按理说应该是两方都进行维护外键关系(这里我建了个中间表,具体见下面解释),但是实际情况是两个人都没有维护,中间表没有任何变化。。。经过多个测试和网上一些资料的参考,我觉得inverse或许理解为”ignore relationship”比较好,也就是说如果the owner of the xml设置了inverse=false,说明它不忽略外键关系的维护,也就是说它负责维护外键关系,如果设置为true就说明它忽略外键关系的维护,由另一方进行维护。

    举例—— 一对多

    班级类和学生类是一对多的关系,在这里我在班级类中设置学生类的引用

    private Set<Student> students=new HashSet<Student>(); public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; } <set name="students" table="student" cascade="save-update" lazy="false"> <key column="gid"></key> <one-to-many class="entity.Student"/> </set>

    (1)现在我设置set的inverse属性等于true <set name="students" table="student" cascade="save-update" lazy="false"> 进行测试

    Grade g=new Grade("java开发","java开发一班"); Student stu1=new Student("张三","女"); Student stu2=new Student("李四","男"); Session session=HibernateSessionFactoryUtil.getSession(); Transaction tx=session.beginTransaction(); g.getStudents().add(stu1); g.getStudents().add(stu2); session.save(g); tx.commit(); HibernateSessionFactoryUtil.closeSession(session);

    控制台显示: Hibernate: select max(gid) from grade Hibernate: select max(sid) from student Hibernate: insert into grade (gname, gdesc, gid) values (?, ?, ?) Hibernate: insert into student (sname, sex, sid) values (?, ?, ?) Hibernate: insert into student (sname, sex, sid) values (?, ?, ?)

    可以发现执行了语句包括对grade的gname,gdesc,gid的添加,同时因为我设置了Grade的cascade为save-update,并且有g的students属性我都赋值为为stu1和stu2,所以系统也会自动添加stu1和stu2的sname、sex、sid,但是gid并没有赋值,因为在这里我设置了Grade的inverse值为true,所以Grade会ignore外键关系的维护,那么student表中gid自然不会添加,查看数据库结果验证如下:

    student表: grade表

    (2)设置grade.hbm.xml的set标签的inverse属性为false,进行测试

    <set name="students" table="student" cascade="save-update" inverse="false"> <key column="gid"></key> <one-to-many class="entity.Student"/> </set>

    做同样的测试,控制台显示: Hibernate: select max(sid) from student Hibernate: insert into grade (gname, gdesc, gid) values (?, ?, ?) Hibernate: insert into student (sname, sex, sid) values (?, ?, ?) Hibernate: insert into student (sname, sex, sid) values (?, ?, ?) Hibernate: update student set gid=? where sid=? Hibernate: update student set gid=? where sid=?

    可以看到首先进行了grade的存储,然后因为cascade的原因对student进行存储,存储之后还新增了两句update语句让student设置gid,显然这时候,因为inverse=false,表示不ignore外键维护关系,所以在add完对象之后,还要维护外键关系,数据库的内容和意料中一样:

    主要看student表:

    举例——多对多

    学生和教师之间的关系是多对多的,现在我设置他们双向多对多,也就是学生中含有教师的引用,教师含有学生的引用: Student.java包含以下语句:

    private Set<Teacher> teachers=new HashSet<Teacher>(); public Set<Teacher> getTeachers() { return teachers; } public void setTeachers(Set<Teacher> teachers) { this.teachers = teachers; }

    Teacher.java包含以下语句:

    private Set<Student> students=new HashSet<Student>(); public Set<Student> getStudents() { return students; } public void setStudents(Set<Student> students) { this.students = students; }

    同时除了student表和teacher表之外,还建立了维护两者关系的teachers_stuents表:

    student.hbm.xml

    <set name="teachers" table="teachers_students" cascade="all" > <key column="sid" /> <many-to-many class="entity.Teacher" column="tid"></many-to-many> </set>

    teacher.hbm.xml

    <set name="students" table="teachers_students" cascade="all"> <key column="tid"></key> <many-to-many class="entity.Student" column="sid"></many-to-many> </set>

    首先我说出我的结论:

    以student类举例,如果它对应的.hbm.xml的set标签的inverse属性设置为false,那么当对student对象进行save时(这里我只介绍save,其他操作类似),首先会检查自己的teacher引用(就是 Set<Teacher>变量)是否为空,如果不为空,同时stuent的hbm.xml的cascade属性设置为save-update(或者设置为all)时,存储完student对象以后,会存储与这个student相关联的teacher对象,同时因为student需要对外键关系负责,所以也会往teachers_students表中添加外键关系。需要注意的是,如果student设置了inverse为false,cascade没有设置save-update或者all,在save student对象的时候,需要手动save teacher对象,因为inverse设置为false之后,Set<Teacher>又不为空,那么系统会往teachers_students表中添加外键关系,但是因为teachers_students表中tid对应的值为空,就会报no references异常。

    上面一段话如果不是很容易理解,请看下面的例子(下面所有例子cascade都为save-update)

    (1)student.hbm.xml的inverse=false,teacher.hmb.xml的inverse=true

    teacher.hmb.xml

    <set name="students" table="teachers_students" cascade="save-update" inverse="true"> <key column="tid"></key> <many-to-many class="entity.Student" column="sid"></many-to-many> </set>

    student.hmb.xml

    <set name="teachers" table="teachers_students" cascade="save-update" inverse="false"> <key column="sid" /> <many-to-many class="entity.Teacher" column="tid"></many-to-many> </set>

    测试1:

    Student s=new Student("学生1","女"); Teacher t1=new Teacher("张三"); t1.getStudents().add(s); session.save(t1);

    运行结果: Hibernate: select max(tid) from teacher Hibernate: select max(sid) from student Hibernate: insert into teacher (tname, tid) values (?, ?) Hibernate: insert into student (sname, sex, sid) values (?, ?, ?)

    首先存储teacher,然后因为cascade为save-update,存储student,因为teacher不负责外键关系,所以没有insert into teachers_students…的语句

    测试2:

    Student s=new Student("学生1","女"); Teacher t1=new Teacher("张三"); s.getTeachers().add(t1);//s的set属性设置了t1对象的值 t1.getStudents().add(s); session.save(t1);

    执行之后: Hibernate: select max(tid) from teacher Hibernate: select max(sid) from student Hibernate: insert into teacher (tname, tid) values (?, ?) Hibernate: insert into student (sname, sex, sid) values (?, ?, ?) Hibernate: insert into teachers_students (sid, tid) values (?, ?)

    发现新增了最后一句往teachers_students表中添加值。这个也很好理解,首先save teacher,因为teacher的cascade为save-update并且teacher的Set<Stuedent>值不为空,所以接下来save set对应的student,存储student 的时候发现student的inverse是false,也就是要维护外键关系,同时student的Set<Teacher>不为空,于是就会往teachers_students表中添加值

    查看数据库的值更容易理解: student表(这里的gid是和前面一对多里面grade对应的外键,在此请忽略) teacher表: teachers_students表:

    测试3:

    Student s=new Student("学生1","女"); Teacher t1=new Teacher("张三"); session.save(t1);

    执行结果: Hibernate: select max(tid) from teacher Hibernate: insert into teacher (tname, tid) values (?, ?)

    只save了teacher,这个很好理解,因为teacher的Set<Student>属性此时为空嘛,自然不会存储任何级联值,当然也不会有外键维护

    (2)student.hbm.xml的inverse=true,teacher.hmb.xml的inverse=false

    测试1:

    Student s=new Student("学生1","女"); Teacher t1=new Teacher("张三"); t1.getStudents().add(s); session.save(t1);

    执行结果: Hibernate: select max(tid) from teacher Hibernate: select max(sid) from student Hibernate: insert into teacher (tname, tid) values (?, ?) Hibernate: insert into student (sname, sex, sid) values (?, ?, ?) Hibernate: insert into teachers_students (tid, sid) values (?, ?)

    很好理解了吧,t1的cascade为save-update,同时其Set<Student>又不为空,save完t1之后自然要save s,然后因为teacher负责维护外键关系,所以有最后一句

    测试2:

    Student s=new Student("学生1","女"); Teacher t1=new Teacher("张三"); s.getTeachers().add(t1); session.save(s);

    执行结果: Hibernate: select max(sid) from student Hibernate: select max(tid) from teacher Hibernate: insert into student (sname, sex, sid) values (?, ?, ?) Hibernate: insert into teacher (tname, tid) values (?, ?)

    很好理解了,不解释了

    (3)student.hbm.xml的inverse=false,teacher.hmb.xml的inverse=false

    测试1:

    明显 t.getStudents().add() save(t)或者 s.getTeachers().add() save(s)任写一个就可以了

    Student s=new Student("学生1","女"); Teacher t1=new Teacher("张三"); s.getTeachers().add(t1); session.save(s);

    结果: Hibernate: select max(sid) from student Hibernate: select max(tid) from teacher Hibernate: insert into student (sname, sex, sid) values (?, ?, ?) Hibernate: insert into teacher (tname, tid) values (?, ?) Hibernate: insert into teachers_students (sid, tid) values (?, ?)

    Student s=new Student("学生1","女"); Teacher t1=new Teacher("张三"); t1.getStudents().add(s); session.save(t1);

    执行结果: Hibernate: select max(tid) from teacher Hibernate: select max(sid) from student Hibernate: insert into teacher (tname, tid) values (?, ?) Hibernate: insert into student (sname, sex, sid) values (?, ?, ?) Hibernate: insert into teachers_students (tid, sid) values (?, ?)

    注意:t.getStudents().add() save(t)和 s.getTeachers().add() save(s)两者不能同时写,因为两个都为false,说明都维护外键关系,此时两个人同时对teachers_students save值会冲突

    (4)student.hbm.xml的inverse=true,teacher.hmb.xml的inverse=true

    这个表示两者都不维护外键关系,即时studnet和teacher都进行add对方的引用,也不会对teachers_students表添加任何值

    Student s=new Student("学生1","女"); Teacher t1=new Teacher("张三"); s.getTeachers().add(t1); t1.getStudents().add(s); session.save(t1); session.save(s);

    执行结果: Hibernate: select max(tid) from teacher Hibernate: select max(sid) from student Hibernate: insert into teacher (tname, tid) values (?, ?) Hibernate: insert into student (sname, sex, sid) values (?, ?, ?)

    转载请注明原文地址: https://ju.6miu.com/read-156239.html

    最新回复(0)