Hibernate一对多、多对一关联关系的使用

本文深入探讨了Hibernate框架中双向关联的实现原理与操作细节,包括不同配置选项对数据操作的影响,以及inverse属性如何改变关联关系的维护方。

双向关联:

Student.hbm.xml

    <class name="model.Student" table="student" lazy="true"

       select-before-update="true"><!--把类和数表关联起来-->

       <id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->

           <generator class="uuid.hex" />

       </id>

       <property name="cardId" type="string" /><!--映射号-->

       <property name="name" type="string" /><!--映射学生名-->

       <property name="age" type="int" /><!--映射学生岁数-->

       <many-to-one name="team"

           column="team_id"

           class="model.Team"

           cascade="none"

           fetch="join"

       /><!--映射班级-->

    </class>

Team.hbm.xml

<class name="model.Team" table="team" lazy="true">

       <id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->

           <generator class="uuid.hex" />

       </id>

       <property name="teamName" type="string" />

       <set name="students" cascade="save-update"  inverse="true" lazy="true">

           <key column="team_id" />

           <one-to-many class="model.Student" />

       </set>

    </class>

<many-to-one>标签具有column属性,column总是和关联类(对于student类来说,关联类是team)的主键id相对应,因此hibernate会根据student表中的team_id,根据Team表中设置的id列,取出team.id=student.team_id的记录,构造成Team对象返回给Student对象。

1 不设置inverse标签

测试类:

Student newStu=new Student();

           newStu.setCardId("12345");

           session = HibernateUtil.currentSession(); //开启连接

           tx = session.beginTransaction(); //开启事务

           Team team=(Team) session.get(Team.class,"ff80808105416d3b0105416d3eca0002");

           Student removeStudent = (Student)session.get(Student.class, "ff80808105416d3b0105416d3eca0001");

           team.getStudents().add(newStu);

           team.getStudents().remove(removeStudent);

 

控制台输出结果:

l  Hibernate: select team0_.id as id2_0_, team0_.teamName as teamName2_0_ from team team0_ where team0_.id=?

l  Hibernate: select student0_.id as id0_1_, student0_.cardId as cardId0_1_, student0_.name as name0_1_, student0_.age as age0_1_, student0_.team_id as team5_0_1_, team1_.id as id2_0_, team1_.teamName as teamName2_0_ from student student0_ left outer join team team1_ on student0_.team_id=team1_.id where student0_.id=?

l  Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id0_0_, students0_.cardId as cardId0_0_, students0_.name as name0_0_, students0_.age as age0_0_, students0_.team_id as team5_0_0_ from student students0_ where students0_.team_id=?

l  Hibernate: insert into student (cardId, name, age, team_id, id) values (?, ?, ?, ?, ?)

l  Hibernate: update student set team_id=null where team_id=? and id=?

l  Hibernate: update student set team_id=? where id=?

第五条语句是由team.getStudents().remove(removeStudent);语句引起的,从学生集合中删除一个学生,所以要将学生的team_id 设置为空,由于级联为设置delete-orphan,也就并不发送delete语句删除学生在数据库中的记录。

第四条语句已经加入了team_id字段,是因为设置了双向关联,但其实插入的值为空。

第六条语句来将此新添学生的team_id 设置为一个正确的值。

这个例子新添加学生的过程是先插入后更新。

 

对测试类进行一下修改,

测试类:(学生添加班级方式)

    Student newStu=new Student();

           newStu.setCardId("12345");

           session = HibernateUtil.currentSession(); //开启连接

           tx = session.beginTransaction(); //开启事务

           Team team=(Team) session.get(Team.class,"ff80808105416d3b0105416d3eca0002");

           newStu.setTeam(team);

           session.save(newStu);

控制台输出如下:

Hibernate: select team0_.id as id2_0_, team0_.teamName as teamName2_0_ from team team0_ where team0_.id=?

Hibernate: insert into student (cardId, name, age, team_id, id) values (?, ?, ?, ?, ?)

 

 

2 设置inverse标签为true

Team.hbm.xml

<class name="model.Team" table="team" lazy="true">

       <id name="id" unsaved-value="null"><!--id的产生方式是uuid.hex-->

           <generator class="uuid.hex" />

       </id>

       <property name="teamName" type="string" />

       <set name="students" cascade="save-update" inverse="true" lazy="true">

           <key column="team_id" />

           <one-to-many class="model.Student" />

       </set>

    </class>

 

测试类:(班级添加学生)

  Student newStu=new Student();

           newStu.setCardId("12345");

           session = HibernateUtil.currentSession(); //开启连接

           tx = session.beginTransaction(); //开启事务

           Team team=(Team) session.get(Team.class,"ff80808105416d3b0105416d3eca0002");

           team.getStudents().add(newStu);

控制台输出:

l  Hibernate: select team0_.id as id2_0_, team0_.teamName as teamName2_0_ from team team0_ where team0_.id=?

l  Hibernate: select students0_.team_id as team5_1_, students0_.id as id1_, students0_.id as id0_0_, students0_.cardId as cardId0_0_, students0_.name as name0_0_, students0_.age as age0_0_, students0_.team_id as team5_0_0_ from student students0_ where students0_.team_id=?

l  Hibernate: insert into student (cardId, name, age, team_id, id) values (?, ?, ?, ?, ?)

测试类在执行完add(newStu)之后并没有调用Sessionupdate()方法更新Team对象,是因为Team对象已经是持久化对象,在清理缓存时会自动调用update()方法。

第一条:get()方法立即加载Team对象

第二条:team.getStudents()方法加载此Team中所有的学生对象

第三条:插入新的学生记录

 

学生添加班级的性能会好一些,因为班级添加学生时候要加载所有的学生对象,有点多余

此时新建学生的team_id值为null,由于在Team.hbm.xml中设置了inverse=true”,teamstudent之间的关系由student来维护,因此当team掌握维护权时(inverse=false”或默认状态),他负责将自己的id告诉student,然后hibernate发送update语句去更新记录。但是现在设置了inverse=true”,维护权在student手中,于是hibernate不再发送update语句,而是由student自己去取得team_id,而这个取得team_id的动作,其实就是完成一个“学生添加班级”的动作,也就是语句newStu.setTeam(team)(将此句话加入测试类),两次运行程序控制台的输出相同,但是数据库的结果不相同,新添加的学生得到了正确的team_id值。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值