Hibernate照射之多对一映射(四)
Hibernate映射之多对一映射(四)
一、单向的多对一
多对一的关系和关系型数据库中外键参照关系最匹配,在多方表中有一个外键,指向一方表的主键。
单向的多对一映射是我在项目中使用最多的一种配置。
实现:单向的多对一映射关系实现是由多方来维护的。在多方持有一方的引用,在多方的映射文件中配置<many-to-one>属性。
还以之前的学生和班级为基础来看一下具体实现:
说明一下:和单向的一对多一样,单向的多对一也只能通过多来导航到一,是单向的,可以通过学生来导航到班级进行相应的操作,并不能通过班级来导航到学生。
1.持久化类
Grade:
Students:需要注意,在Students持久化类中添加了对Grade的引用,并且提供了set/get
2.映射文件
在多方维护,所以Grade.hbm.xml并没有特别之处。
需要在Students.hbm.xml中添加对应外键的映射也就是<many-to-one>
通过以上的配置就可以对这两个表进行操作了。
二、双向关联关系
实现:一方为one,一方为many,同时配置<many-to-one>和<set>来建立双向的关联关系。
通过双向的关联关系我们搭建了双向的导航,可以从学生导航到班级,也可以通过班级导航到
学生,只不过性能上需要通过配置来优化一下,下面会说。
还是基于学生和班级来说:
1.持久化类
Grade中保存Students的set集合
Students中保存Grade的引用
2.映射文件
Grade.hbm.xml中配置Students的外键
同时需要在Grade.hbm.xml中配置映射关系
3.测试类
相应的执行sql如下图:

注意:在这里需要注意一下,因为是双向的关联关系,除了正常的3个insert语句还有2个update更新语句,这是由于Grade中维护一对多关系时产生的。此时为了提高性能,可以在set标签中添加一个设置inverse="true",表明关联关系的维护由多方来维持。
之后再去测试一下,就没有多余的update语句了:

查询验证:
配置默认的是执行懒加载模式:就是现在学生与班级有多对一的关联关系,但是查询学生的时候不会默认查询相应班级的信息,当使用到班级信息的时候再去执行查询。
执行的sql:

执行的sql

从结果可以看出来,只有用到相关grade信息时,才去执行的select查询grade表:这个就叫做懒加载。
此时如果想要在获取到students信息的时候就已经获取到全部包含grade的信息时就需要在<many-to-one>中添加一个属性配置
此时再次执行上面查询代码:

此时就是全部查询出来的。
这个属性的配置根据需求来定,因为涉及到一定的性能。
一、单向的多对一
多对一的关系和关系型数据库中外键参照关系最匹配,在多方表中有一个外键,指向一方表的主键。
单向的多对一映射是我在项目中使用最多的一种配置。
实现:单向的多对一映射关系实现是由多方来维护的。在多方持有一方的引用,在多方的映射文件中配置<many-to-one>属性。
还以之前的学生和班级为基础来看一下具体实现:
说明一下:和单向的一对多一样,单向的多对一也只能通过多来导航到一,是单向的,可以通过学生来导航到班级进行相应的操作,并不能通过班级来导航到学生。
1.持久化类
Grade:
private int gid; private String gname; private String gdesc;
Students:需要注意,在Students持久化类中添加了对Grade的引用,并且提供了set/get
private int sid; private String sname; private Grade grade; public Grade getGrade() { return grade; } public void setGrade(Grade grade) { this.grade = grade; }
2.映射文件
在多方维护,所以Grade.hbm.xml并没有特别之处。
<hibernate-mapping> <class name="com.iteye.sunyq.hibernate.Grade" table="grade"> <id name="gid" type="integer"> <column name="id"></column> <generator class="native"></generator> </id> <property name="gname" type="string"> <column name="gname"></column> </property> <property name="gdesc" > <column name="gdesc"></column> </property> </class> </hibernate-mapping>
需要在Students.hbm.xml中添加对应外键的映射也就是<many-to-one>
<hibernate-mapping> <class name="com.iteye.sunyq.hibernate.Students" table="students"> <id name="sid" type="integer"> <column name="id"></column> <generator class="native"></generator> </id> <property name="sname" type="string"> <column name="sname"></column> </property> <many-to-one name="grade" class="com.iteye.sunyq.hibernate.Grade"> <column name="gid"></column> </many-to-one> </class> </hibernate-mapping>
通过以上的配置就可以对这两个表进行操作了。
二、双向关联关系
实现:一方为one,一方为many,同时配置<many-to-one>和<set>来建立双向的关联关系。
通过双向的关联关系我们搭建了双向的导航,可以从学生导航到班级,也可以通过班级导航到
学生,只不过性能上需要通过配置来优化一下,下面会说。
还是基于学生和班级来说:
1.持久化类
Grade中保存Students的set集合
... private int gid; private String gname; private String gdesc; private Set<Students> studentSet = new HashSet<Students>(); ...
Students中保存Grade的引用
private int sid; private String sname; private Grade grade;
2.映射文件
Grade.hbm.xml中配置Students的外键
<set name="studentSet" inverse="true"> <key column="gid"/><!-- Students表中外鍵名称 --> <one-to-many class="com.iteye.sunyq.hibernate.Students"></one-to-many><!-- 映射的实体类 --> </set>
同时需要在Grade.hbm.xml中配置映射关系
<many-to-one name="grade" class="com.iteye.sunyq.hibernate.Grade"> <column name="gid"></column> </many-to-one>
3.测试类
Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Grade g = new Grade("班级一", "班级一描述"); Students s1 = new Students("学生1"); Students s2 = new Students("学生1"); g.getStudentSet().add(s1); g.getStudentSet().add(s2); s1.setGrade(g); s2.setGrade(g); session.save(g); session.save(s1); session.save(s2); transaction.commit(); HibernateUtil.closeSession(session);
相应的执行sql如下图:
注意:在这里需要注意一下,因为是双向的关联关系,除了正常的3个insert语句还有2个update更新语句,这是由于Grade中维护一对多关系时产生的。此时为了提高性能,可以在set标签中添加一个设置inverse="true",表明关联关系的维护由多方来维持。
<set name="studentSet" inverse="true"> <key column="gid"/><!-- Students表中外鍵名称 --> <one-to-many class="com.iteye.sunyq.hibernate.Students"></one-to-many><!-- 映射的实体类 --> </set>
之后再去测试一下,就没有多余的update语句了:
查询验证:
配置默认的是执行懒加载模式:就是现在学生与班级有多对一的关联关系,但是查询学生的时候不会默认查询相应班级的信息,当使用到班级信息的时候再去执行查询。
Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Students s = (Students) session.get(Students.class, 2); System.out.println(s.getSname()); transaction.commit(); session.close();
执行的sql:
Session session = HibernateUtil.getSession(); Transaction transaction = session.beginTransaction(); Students s = (Students) session.get(Students.class, 2); System.out.println(s.getSname()); Grade g =s.getGrade(); System.out.println(g.getGname()); transaction.commit(); session.close();
执行的sql
从结果可以看出来,只有用到相关grade信息时,才去执行的select查询grade表:这个就叫做懒加载。
此时如果想要在获取到students信息的时候就已经获取到全部包含grade的信息时就需要在<many-to-one>中添加一个属性配置
<many-to-one name="grade" class="com.iteye.sunyq.hibernate.Grade" lazy="false"> <column name="gid"></column> </many-to-one>
此时再次执行上面查询代码:
此时就是全部查询出来的。
这个属性的配置根据需求来定,因为涉及到一定的性能。