inverse属性

前言

查看这篇博客: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 (?, ?, ?)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值