在现实生活中 ,很少有对象是孤立存在的,例如老师,往往和被授课的学生存在关联关系,如果得到了某个老师实例,那么我们就可以直接获取该老师
对应的全部学生。同样,我们得到了一个学生实例 ,我们也可以获取所有教授他课程的老师。
关联关系大致可以分为两类 :
单向关联 :只需单向访问关联端。
双向关联:关联的两端可以互相访问。
首先来看双向关联:
双向 1—1关联:
这里使用 人与身份证的例子
双向:通过一个人(存在主数据表中) 我们可以找到这个人的身份证(存在从数据表中) 通过一个身份证 也可以找到人
(在代码中的体现是 通过Person类的实例对象,通过get方法可以拿到IDCard类的实力对象;通过IDCard类的实例对象,通过get方法可以拿到Person类的实例对象。
所以双方的类中需要互相定义一个对方的属性 )
1-1:主数据表的一个人 只能对应于从数据表中的 一个身份证 一个身份证也只能对应于一个人
双向1-1关联又可以根据使用的关联字段分为 基于外键的双向1-1关联 基于主键的双向1-1关联
基于外键的双向1-1关联
持久化类 Person类 有一个 IDCard类型的属性 private IDCard idcard;
持久化类 IDCard类 有一个 Person类型的属性 private Person person;
映射文件配置 :
<class name="org.lingtong.pojo.Person" table="tb_person">
<id name="id" column="id">
<generator class="native" /> //指定tb_person表的主键生成策略
<id>
...... //省略 name属性 sex属性与对应数据列的映射关系
<one-to-one name="idcard" property-ref="person"></one-to-one>
</class>
<class name="org.lingtong.pojo.IDCard" table="tb_IDCard">
<id name="id" column="id">
<generator class="native" /> //指定tb_IDCard表的主键生成策略
<id>
...... //省略 code属性与对应数据类的映射关系
<many-to-one name="person " column="p_id" unique="true" not-null="true"></many-to-one> //p_id列会去关联主表的主键列
</class>
基于主键的双向1-1关联
持久化类 Person类 有一个 IDCard类型的属性 private IDCard idcard;
持久化类 IDCard类 有一个 Person类型的属性 private Person person;
映射文件配置:
<class name="org.lingtong.pojo.Person" table="tb_person">
<id name="id" column="id">
<generator class="native" /> //指定tb_person表的主键生成策略
<id>
...... //省略 name属性 sex属性与对应数据列的映射关系
<one-to-one name="idcard" property-ref="person"></one-to-one>
</class>
<class name="org.lingtong.pojo.IDCard" table="tb_IDCard">
<id name="id" column="id">
<generator class="foreign">
<param name="property">person</param>
</generator>
</id>
........ //省略 code属性 与对应数据列的映射关系
<one-to-one name="person" constrained="true"></one-to-one>
</class>
双向1-N关联:
这里使用人与房产的例子
双向:通过一个人(存在主数据表中)可以找到这个人的所有房产(存在从数据表中) 通过一处房产 我们可以找到拥有这处房产的那个人
(在代码中的体现是 通过Person类的实例对象,通过get方法可以拿到存有House类的实力对象的集合;通过House 类的实例对象,通过get方法可以拿到Person类的实例对象。
所以双方的类中需要互相定义一个对方的属性 )
1-N : 一个人可以拥有多处房产 但一处房产只能对应于一个人
持久化类 Person类 拥有一个集合类型(该集合中存House类型对象)的属性 private Set<House> houseList;
持久化类 House类 用于 一个Person类型的属性 private Person person;
映射文件配置 :
<class name="org.lingtong.pojo.Person" table="tb_person">
<id name="id" column="id">
<generator class="native" /> //指定tb_person表的主键生成策略
<id>
...... //省略 name属性 sex属性与对应数据列的映射关系
<Set name="houseList" inverse="true"> //inverse属性表示是否把这种 关联关系 交给对方表去管理(Hibernate推荐把关系交给N的一端去管理)
<key column="p_id"></key> //如果使用的是list或者其他集合类型 可以添加<list-index>等相关元素
<one-to-many class="org.lingtong.pojo.House"></one-to-many>
</Set>
</class>
<class name="org.lingtong.pojo.House" table="tb_house">
<id name="id" column="id">
<generator class="native" /> //指定tb_house表的主键生成策略
<id>
......... //省略 address属性与对应数据类的映射关系
<many-to-one name="person" column="p_id" not-null="true"></many-to-one>
</class>
双向N-N关联
这里是教师与学生的例子
双向 :通过一个老师(存在主数据表中) 可以访问 他所带的每一个学生(存在从数据表中)
(在代码中的体现是 通过Teacher类的实例对象,通过get方法可以拿到存有Student类的实力对象的集合;通过Student 类的实例对象,通过get方法可以拿到存有Teacher类的实例对象的集合。
所以双方的类中需要互相定义一个对方的属性 )
N-N : 一个老师 可以带多个学生 一个学生可以由多个老师 (所带科目不同)
双向多对多的关联 需要借助第三方表 ----中间表
持久化类 Teacher类 拥有一个集合类型(该集合中存放Student类型的对象)的属性 private Set<Student> studentSet;
持久化类 Student类 拥有一个集合类型(该集合中存放Teacher类型的对象)的属性 private Set<Teacher> teacherSet;
映射文件配置 :
<class name="org.lingtong.pojo.Teacher" table="tb_Teacher">
<id name="id" column="id">
<generator class="native" />
</id>
...... //省略 teacherName 属性 与 subject属性与对应列的映射关系
<set name="studentSet" table="tb_teacher_student">
<key column="t_id" ></key>
<many-to-many column="s_id" class="org.lingtong.pojo.Student"></many-to-many>
</set>
</class>
<class name="org.lingtong.pojo.Student" table="tb_Student">
<id name="id" column="id">
<generator class="native" />
</id>
...... //省略 studentName 属性 与 class属性与对应列的映射关系
<set name="studentSet" table="tb_teacher_student">
<key column="s_id" ></key>
<many-to-many column="t_id" class="org.lingtong.pojo.Teacher"></many-to-many>
</set>
</class>
相对于较为复杂的双向关联 ,单向关联稍微简单