作为一种轻量级的关系映射工具,Hibernate支持各种关系映射,例如:多对一、一对多和一对一的数据库表关系,通过映射文件的灵活配置即可轻松实现。Hibernate的重要部分就是关系映射。本章我们将会就这几个关系进行说明介绍:
- 单向多对多映射
- 双向多对多映射
- 单向多对一映射
- 单向一对多映射
- 双向一对多(多对一)映射
- 基于外键的单向一对一映射
- 基于外键的双向一对一映射
- 基于主键的单向一对一映射
- 基于主键的双向一对一映射
这里,在介绍的过程中,会着重介绍配置文件的核心代码变化,而忽略掉Test测试方法。另外,需要注意的是基于外键、主键以及无任何的关系与变化。
1.1 单向多对多映射
这里我们使用实例来进行说明:
假设有角色和用户组两个表,是多对多的关系,即一个角色可以多个用户组拥有,一个用户组也可以拥有多个角色。这里我们在进行编写的时候呢,就需要增加一个角色-组的对应表,用来记录多对多的关系。
例如一个网站的用户角色可以有查看、添加、删除和修改等功能,用户又可以分为管理员、版主、注册用户和匿名用户等,那么这里的用户和角色就是多对多的关系,即一个用户可以拥有多个角色,每个角色也可以赋给多个用户。
步骤:
1.建立角色表、用户表以及角色-用户表。第三个表主要就是将他们在各自关系表中的主键属性进行创建一个表。
2.建立角色实体类。这里我们需要注意的是将用户表也进行实例化,也就是在创建的时候,需要建立一个集合类型属性变量,这样才能展现出多个用户。
private Set groups = new HashSet();
3.建立用户组的实体类
这里与上面的是一致的,也需要将角色表进行实例化。
private Set roles = new HashSet();
4.因为角色端是多对多的控制方,其映射文件可以进行编写:
<!-- 配置多对多关系映射 -->
<set name="groups" cascade="save-update">
<key column="role_id"></key>
<many-to-many class="*" column="group_id"></many-to-many>
</set>
5.Group(用户组)是被控制方,在进行编写的时候,我们不需要进行特别的主要,就像原来的那么编写即可。
6.编写测试类Test
这里笔者就不一一说明测试类的书写了,这里我们只需要注意Set集合的编写方法。
1.2 双向多对多映射
我们还是使用上面的例子进行说明。
首先,根据上面的步骤,我们需要修改角色端映射文件的代码书写。
这里我们需要在Set标签中再加入一个属性——inverse。
inverse属性负责控制关系,默认为false,也就是关系的两端都能控制,但这样会造成一些问题。更新时会因为两端都控制关系,于是重复更新。一般来说有一端要设为true,也就是让另一端进行控制关系。
第二,我们需要在用户组映射文件中进行编写。
<!-- 配置多对多关系映射 -->
<set name="roles" cascade="save-update">
<key column="group_id"></key>
<many-to-many class="*" column="role_id"></many-to-many>
</set>
这样,我们就比较好的将双向与单向多对多的映射进行了比较与介绍。
1.3 单向多对一映射
在数据库表关系中,经常出现多对一的映射,例如一个人只能有一个住址(假定),一个住址可以住多个人。那么人和住址就是多对一的关系。
步骤:
1.建表,人(Person)、住址(address)。
2.建实体类,这里只需要在多的那一端也就是人实体类建立一个住址属性变量。
private Address address;
而另外一端,则如同正常的实体类一般进行编写即可。
3.建立Person.hbm.xml映射文件:
<!-- 配置多对一的关联关系 -->
<many-to-one name="address" column="address_id"></many-to-one>
就能达到控制单向多对一关系映射。
4建立Address.hbm.xml映射文件
不需要进行特别的配置,略过。。。
5.添加测试类Test
1.4单向一对多映射
比较典型的一对多映射就是公司与雇员的关系,即一个公司可以有多个雇员。
单向一对多的映射关系并不是很常见,其配置同单向多对一非常相似,其主动方为“一”的一方,使用one-to-many配置属性。
步骤:
1.建表。公司表(company)、雇员表(employee)。
2.建公司与雇员的实体类。略。PS:我想有点读者已经发现了,多与一的时候,我们只需要在一的那边编写类的属性变量。
3.编写公司映射文件Company.hbm.xml。
<!-- 配置一对多关系映射 -->
<set name="employees" cascade="all">
<key column="com_id"></key>
<one-to-many class="*"></many-to-many>
</set>
4.雇员映射文件Employee.hbm.xml
略过,与一般相同。
5.编写测试类Test
1.5 双向一对多(多对一)映射
常见的双向一对多或者是多对一映射是父子关系
步骤:
1.建立数据库表。father、son
2.建立实体类
3.映射文件Father.hbm.xml的配置
<!-- 配置一对多关系映射 -->
<set name="sons" cascade="all" incerse="true">
<key column="father_id"></key>
<one-to-many class="*"></many-to-many>
</set>
4.映射文件Son.hbm.xml配置
<!-- 配置多对一的关联关系 -->
<many-to-one name="father" column="father_id"></many-to-one>
5.编写测试类Test
1.6 基于外键的单向一对一映射
基于外键的单向一对一映射,常见的例子是用户(user)和电子邮件(email),每个用户只有一个电子邮件,并通过外键email_id同电子邮件相对应。但是电子邮件没有对应的用户
步骤:
1.建立email、user数据库表
2.建立实体类。
在User.java中,我们需要定义一个邮件类型变量
private Email email;
3.映射文件User.hbm.xml
<!-- 配置多对一的关联关系 -->
<many-to-one name="email" column="email_id" class="*" unique="true">
</many-to-one>
在这个映射文件中,我们给many-to-one配置了一个unique属性。
配置这个属性的作用是不能有重复的主键,就限定了"多"的一方必须变成“一”,这样就实现了一对一映射。单向的一对一映射,只需要配置一方即可。
4.映射文件Email.hbm.xml
与一般相同即可。
5.编写测试类Test
1.7基于外键的双向一对一映射
修改前一节单项映射为双向映射。在保持数据库表不变的情况下,增加相应的配置信息,实现双向映射。例如:用户表与电子邮件就是双向一对一的映射关系,即每个用户都有唯一的电子邮件对应,例如常见的电子商务网站淘宝和ebay等,一对一可以通过主键对应,也可以通过外键来对应。
- one-to-one
- property-ref
步骤:
1.数据库表结构与上节一样
2.双向所以两个实体类都要进行编写类属性变量
3.映射文件User.hbm.xml
<!-- 配置一对一的关联关系 -->
<many-to-one name="email" column="email_id" unique="true">
</many-to-one>
4.映射文件Email.hbm.xml
<!-- 配置一对一的关联关系 -->
<one-to-one name="user" property-ref="email">
</one-to-one>
property-ref属性:指定关联类的一个属性,这个属性将会和本外键相对应。如果没有指定,会使用对方关联类的主键
5.编写测试类Test
1.8 基于主键的单向一对一映射
一对一映射,前面介绍的是基于外键的,还有一种基于主键的一对一映射,即两个表的主键值相同。单向一对一的情况不多,例如用户和电子邮件之间的关系,假定没有用户必须有唯一的电子邮件与之对应,而电子邮件可以没有对应的用户,即对应关系是单向的。
基于主键的一对一映射特点是两个表都以主键作为关联字段,这同基于外键的一对一映射有很大的不同,即关联字段都是各自的主键。
步骤:
1.建表。同时都以ID作为主键。
2.建立实体类。这里和基于外键的不同是单向两个实体类同时都要建立类属性变量。
3.Emailpk.hbm.xml映射文件
这里呢?有一个比较重要的属性。
<id ... >
<column .../>
<generator class="foreign">
<param name-"property">userpk</paprm>
<generator>
</id>
...
<one-to-one name="userpk" class="*" constrained="true">
</one-to-one>
这里,我们引进了几个其他的属性。
generator class="foreign" 意味着Emailpk使用外部主键,<param name="property">userpk</param>配置了Emailpk使用Usepk的主键作为自己的主键,这样就实现了基于主键的一对一映射。
constrained="true"说明userpk的主键值存在一个约束,即emailpk使用了userpk的主键。
4.Userpk.hbm.xml映射文件
与一般相同,不做阐述。
5.编写测试文件Test
1.9基于主键的双向一对一映射
前面介绍了基于主键的单向一对一映射,本节介绍基于主键的双向一对一映射,还是使用前面的数据库表和相关类。例如用户和电子邮件之间的关系,每个用户有唯一的电子邮件,每个电子邮件有唯一的用户,假如这种对应是通过各自的主键实现的,那么就是基于主键的双向一对一映射关系。
步骤:
1.建表。
2.编写实体类。
3.映射文件Emailpk.hbm.xml
与上面的一样。
4.映射文件Userpk.hbm.xml
<one-to-one name="emailpk" class="*" constrained="true">
</one-to-one>
5.编写测试类Test。