文章目录
  1. 1. 双向1-1关联
    1. 1.1. 域模型
    2. 1.2. 关系数据模型
      1. 1.2.1. 按照外键映射
      2. 1.2.2. 按照主键映射
  2. 2. 基于外键
    1. 2.1. 介绍
    2. 2.2. 代码
    3. 2.3. Notice
  3. 3. 基于主键
    1. 3.1. 介绍
    2. 3.2. 代码

我最近在复习一下关于Hibernate关系映射的知识,看了书本的介绍以及视频。这几篇博客都是对学到知识的一点总结。当然,这些这是最基本的能够实现关联关系的配置,在实际的使用中,还有很多参数需要根据情况来设置。但也算是对以后开发过程中遇到遗忘的地方可以进行查阅。

在本文中使用的Demo也都已经上传到github中,里边有详细的运行说明。
Hibernate关系映射1:单向N-1关联
Hibernate关系映射2:双向1-N关联
Hibernate关系映射3:双向1-1关联
Hibernate关系映射4:N-N关联

Github地址:HibernateRelationMapping

双向1-1关联


双向1-1关联需要修改两边的持久化类代码,让两个持久化类都增加引用关联实体的属性,并为该属性提供get和set方法。

双向1-1关联有三种映射模式:

  • 基于主键
  • 基于外键
  • 使用连接表

在该文中,将主要介绍前两种模式。

域模型

图1

关系数据模型

按照外键映射

图2

按照主键映射

图3

基于外键


介绍

对于基于外键的1-1关联,外键可以存放在任意一边。需要存放外键的一端,需要增加<many-to-one.../>元素,并且为<many-to-one.../>元素增加unique="true"属性来表示该实体实际上是1的一端。
<many-to-one name="manager" class="Manager" column="MGR_ID" unique="true"></many-to-one>

对于1-1的关联关系,两个实体原本处于平等状态,但当我们选择任意一个表来增加外键后(增加<many-to-one.../>元素的实体端),该表即变成从表,而另一个表则成为主表。

另一端需要使用<one-to-one.../>元素,该<one-to-one.../>元素需要使用name属性指定关联属性名。为了让系统不再为本表增加一列,而是使用外键关联,使用property-ref属性指定引用关联类的属性。
<one-to-one name="department" class="Department" property-ref="manager"></one-to-one>

代码

实体类

1
2
3
4
5
6
7
8
9
10
11
12
public class Department {
private Integer deptId;
private String deptName;
private Manager manager;
//省去get和set
}
public class Manager {
private Integer mgrId;
private String mgrName;
private Department department;
//省去get和set
}

Manager.hbm.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
<hibernate-mapping package="com.lihui.hibernate.double_1_1.foreign">
<class name="Manager" table="MANAGERS">
<id name="mgrId" type="java.lang.Integer">
<column name="MGR_ID" />
<generator class="native" />
</id>
<property name="mgrName" type="java.lang.String">
<column name="MGR_NAME" />
</property>
<!-- 映射1-1的关联关系,在对应的数据表中已经有外键,当前持久花类使用ont-to-one进行映射 -->
<one-to-one name="department" class="Department" property-ref="manager"></one-to-one>
</class>
</hibernate-mapping>

Department.hbm.xml

1
2
3
4
5
6
7
8
9
10
11
12
<hibernate-mapping package="com.lihui.hibernate.double_1_1.foreign">
<class name="Department" table="DEPARTMENTS">
<id name="deptId" type="java.lang.Integer">
<column name="DEPT_ID" />
<generator class="native" />
</id>
<property name="deptName" type="java.lang.String">
<column name="DEPT_NAME" />
</property>
<many-to-one name="manager" class="Manager" column="MGR_ID" unique="true"></many-to-one>
</class>
</hibernate-mapping>

测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
public void testGet(){
Department dep = (Department) session.get(Department.class, 1);
System.out.println(dep.getDeptName());
Manager mgr =dep.getManager();
System.out.println(mgr.getMgrName());
}
@Test
public void testSave() {
Department dep = new Department();
dep.setDeptName("a");
Manager mgr = new Manager();
mgr.setMgrName("b");
dep.setManager(mgr);
mgr.setDepartment(dep);
session.save(mgr);
session.save(dep);
}

Notice

上面的映射策略可以互换,即让Manager存放外键,使用<many-to-one.../>元素映射关联属性;但Department端则必须使用<one-to-one.../>元素映射,万万不可两边都使用相同的元素映射关联属性。

基于主键


介绍

如果采用基于主键的映射策略,则一端的主键生成器需要使用foreign策略,表明将根据对方的主键来生成自己的主键,本实体不能拥有自己的主键声称策略。<param>子元素指定使用当前持久化类的哪个属性作为“对方”。

1
2
3
<generator class="foreign" >
<param name="property">manager</param>
</generator>

当然,任意一端都可以采用foreign主键生成器策略,表明将根据对方主键来生成自己的主键。

采用foreign主键生成器策略的一端增加one-to-one元素映射相关属性,其ont-to-one属性还应增加constrained=true属性;另一端增加one-to-one元素映射关联属性。

constrained:指定为当前持久化类对应的数据库表的主键添加一个外键约束,引用被关联对象所对应的数据库主键。

代码

实体类与上文中的实体类相同。
Manager.hbm.xml

1
2
3
4
5
6
7
8
9
10
11
12
<hibernate-mapping package="com.lihui.hibernate.double_1_1.primary">
<class name="Manager" table="MANAGERS">
<id name="mgrId" type="java.lang.Integer">
<column name="MGR_ID" />
<generator class="native" />
</id>
<property name="mgrName" type="java.lang.String">
<column name="MGR_NAME" />
</property>
<one-to-one name="department" class="Department"></one-to-one>
</class>
</hibernate-mapping>

Department.hbm.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<hibernate-mapping package="com.lihui.hibernate.double_1_1.primary">
<class name="Department" table="DEPARTMENTS">
<id name="deptId" type="java.lang.Integer">
<column name="DEPT_ID" />
<generator class="foreign" >
<param name="property">manager</param>
</generator>
</id>
<property name="deptName" type="java.lang.String">
<column name="DEPT_NAME" />
</property>
<one-to-one name="manager" class="Manager" constrained="true"></one-to-one>
</class>
</hibernate-mapping>

文章目录
  1. 1. 双向1-1关联
    1. 1.1. 域模型
    2. 1.2. 关系数据模型
      1. 1.2.1. 按照外键映射
      2. 1.2.2. 按照主键映射
  2. 2. 基于外键
    1. 2.1. 介绍
    2. 2.2. 代码
    3. 2.3. Notice
  3. 3. 基于主键
    1. 3.1. 介绍
    2. 3.2. 代码