在领域模型中, 类与类之间最普遍的关系就是关联关系.
在 UML 中, 关联是有方向的.
以 Customer 和 Order 为例: 一个用户能发出多个订单, 而一个订单只能属于一个客户. 从 Order 到 Customer 的关联是多对一关联; 而从 Customer 到 Order 是一对多关联
单向关联
双向关联
单向 n-1
单向 n-1 关联只需从 n 的一端可以访问 1 的一端
域模型: 从 Order 到 Customer 的多对一单向关联需要在Order 类中定义一个 Customer 属性, 而在 Customer 类中无需定义存放 Order 对象的集合属性
显然无法直接用 property 映射 customer 属性
Hibernate 使用<many-to-one>
元素来映射多对一关联关系
<many-to-one name="grade" class="com.school.Grade" column="GRADE">
many-one 标签
<many-to-one>
元素来映射组成关系
- name: 设定待映射的持久化类的属性的名字
- column: 设定和持久化类的属性对应的表的外键
- class:设定待映射的持久化类的属性的类型
注意事项
- 在删除grade时,由于student有外键和他相关,是无法删除的。只有和他相关的stuent全被删除后,才可以删除对应grade。
- 在执行插入时,先插入grade,再插入对应student,可以减少select语句。如果顺序颠倒,则需要额外发送select语句查询grade的ID
- 在执行加载时,student的外键 grade属性是懒加载的,如果在使用之前,session被关闭,会出现懒加载异常。如下:
@Test
public void testGet(){
Student student=(Student)session.get(Student.class, 1);
session.close();
System.out.println(student.getGrade());
}
一对多双向关联
双向 1-n 与 双向 n-1 是完全相同的两种情形
双向 1-n 需要在 1 的一端可以访问 n 的一端, 反之依然.
域模型:从 Order 到 Customer 的多对一双向关联需要在Order 类中定义一个 Customer 属性, 而在 Customer 类中需定义存放 Order 对象的集合属性
关系数据模型:ORDERS 表中的 CUSTOMER_ID 参照 CUSTOMER 表的主键
创建集合时的注意事项
当 Session 从数据库中加载 Java 集合时, 创建的是 Hibernate 内置集合类的实例, 因此在持久化类中定义集合属性时必须把属性声明为 Java 接口类型
Hibernate 的内置集合类具有集合代理功能, 支持延迟检索策略
事实上, Hibernate 的内置集合类封装了 JDK 中的集合类, 这使得 Hibernate 能够对缓存中的集合对象进行脏检查, 按照集合对象的状态来同步更新数据库。在定义集合属性时, 通常把它初始化为集合实现类的一个实例. 这样可以提高程序的健壮性, 避免应用程序访问取值为 null 的集合的方法抛出 NullPointerException
private Set< Student> set=new HashSet<Student>();
set标签的配置
Hibernate 使用 <set>
元素来映射 set 类型的属性
<set>
元素来映射持久化类的 set 类型的属性
name: 设定待映射的持久化类的属性的<key>
元素设定与所关联的持久化类对应的表的外键
column: 指定关联表的外键名<one-to-many>
元素设定集合属性中所关联的持久化类
class: 指定关联的持久化类的类名
inverse属性
在hibernate中通过对 inverse 属性的来决定是由双向关联的哪一方来维护表和表之间的关系. inverse = false 的为主动方,inverse = true 的为被动方, 由主动方负责维护关联关系
在没有设置 inverse=true 的情况下,父子两边都维护父子
关系在 1-n 关系中,将 n 方设为主控方将有助于性能改善(如果要国家元首记住全国人民的名字,不是太可能,但要让全国人民知道国家元首,就容易的多)
在 1-N 关系中,若将 1 方设为主控方
- 会额外多出 update 语句。
插入数据时无法同时插入外键列,因而无法为外键列添加非空约束
注意事项
- 在一的一方,同样使用懒加载策略,对于集合,只有在用到时才去初始化。
set标签的级联属性cascade
在对象 – 关系映射文件中, 用于映射持久化类之间关联关系的元素, , <many-to-one>
和 <one-to-one>
都有一个 cascade 属性, 它用于指定如何操纵与当前对象关联的其他对象.
在数据库中对集合排序
<set>
元素有一个 order-by 属性, 如果设置了该属性, 当 Hibernate 通过 select 语句到数据库中检索集合对象时, 利用 order by 子句进行排序order-by 属性中还可以加入 SQL 函数
//order-by 字段名 DESC
<set name="set" inverse="true" order-by="CITY DESC" table="STUDENT" cascade="save-update">
<key column="GRADE"></key>
<one-to-many class="com.school.Student" />
</set>