双向关联:
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)之后并没有调用Session的update()方法更新Team对象,是因为Team对象已经是持久化对象,在清理缓存时会自动调用update()方法。
第一条:get()方法立即加载Team对象
第二条:team.getStudents()方法加载此Team中所有的学生对象
第三条:插入新的学生记录
学生添加班级的性能会好一些,因为班级添加学生时候要加载所有的学生对象,有点多余
此时新建学生的team_id值为null,由于在Team.hbm.xml中设置了inverse=“true”,team和student之间的关系由student来维护,因此当team掌握维护权时(inverse=“false”或默认状态),他负责将自己的id告诉student,然后hibernate发送update语句去更新记录。但是现在设置了inverse=“true”,维护权在student手中,于是hibernate不再发送update语句,而是由student自己去取得team_id,而这个取得team_id的动作,其实就是完成一个“学生添加班级”的动作,也就是语句newStu.setTeam(team)(将此句话加入测试类),两次运行程序控制台的输出相同,但是数据库的结果不相同,新添加的学生得到了正确的team_id值。