Hibernate 关联映射
1. 单向N-1关联
单向N-1关联只需要从N的一端访问1的一端.
如,多人住同一地址,只需要在人的实体端找到地址实体,无需关心一个地址的所有人.
(Person类有个Address类型的Field,而Address类无需关联Person)
1.1 无连接表的N-1关联(基于外键)
Person端增加了Address,该属性不是一个普通的组件,而是引用另一个持久化的类.
使用<many-to-one>在N端(Person端)增加一个外键(关联到address表的主键address_id).
<!-- N-1无连接关联 cascade指定哪些持久化操作会从主表记录级联到从表记录 -->
<many-to-one name="address" cascade="all" class="Address" column="address_id" />
mysql> desc address_inf;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| address_id | int(11) | NO | PRI | NULL | auto_increment |
| addressDetail | varchar(255) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
mysql> desc person_senior_inf;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| person_id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| age | int(11) | YES | | NULL | |
| address_id | int(11) | YES | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
1.2 有连接表的N-1关联
(基于连接表,需要第三张表,保存两个表的id对应关系,这个表中,personid是唯一的,
因为一个person只能属于一个address)
join (P436)
<!-- 有连接表的N-1关联(基于连接表,需要第三张表,保存两个表的id对应关系) -->
<join table="person_address">
<!-- 本表主键 -->
<key column="person_id" />
<!-- 1端表的主键 -->
<many-to-one name="address" cascade="all" class="Address" column="address_id" />
</join>
mysql> desc address_inf;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| address_id | int(11) | NO | PRI | NULL | auto_increment |
| addressDetail | varchar(255) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
mysql> desc person_senior_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| person_id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| age | int(11) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
mysql> desc person_address;
+------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| person_id | int(11) | NO | PRI | NULL | |
| address_id | int(11) | YES | MUL | NULL | |
+------------+---------+------+-----+---------+-------+
2. 单向1-1关联
2.1 基于外键的1-1关联(无连接的)
基本同无连接的N-1,但是需要增加一个unique=true.表示在person表中,address_id也是唯一的(不可重复).
这样一个person对应一个address,一个address也只能对应一个person
mysql> desc address_inf;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| address_id | int(11) | NO | PRI | NULL | auto_increment |
| addressDetail | varchar(255) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
mysql> desc person_senior_inf;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| person_id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| age | int(11) | YES | | NULL | |
| address_id | int(11) | YES | UNI | NULL | |
+------------+--------------+------+-----+---------+----------------+
2.2 有连接表的单向1-1
基本同1.2,需要在many-to-one中新增一个属性,unique=true
mysql> desc address_inf;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| address_id | int(11) | NO | PRI | NULL | auto_increment |
| addressDetail | varchar(255) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
mysql> desc person_senior_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| person_id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| age | int(11) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
mysql> desc person_address;
+------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| person_id | int(11) | NO | PRI | NULL | |
| address_id | int(11) | YES | UNI | NULL | |
+------------+---------+------+-----+---------+-------+
2.3 基于主键的1-1关联.
后端的1先有了,前端的1后生产,前端的1的主键有关联的实体负责生成.
此时address作为主表,有主键,再生成person是,person的主键根据address的主键生成.
因为person和address是一一对应的,所以他们两个可以共享一个id.
因为先生成address,所以person的主键由关联的address来提供.
此时生成的表,只有person_id了,值就是address表中address_id
mysql> desc address_inf;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| address_id | int(11) | NO | PRI | NULL | auto_increment |
| addressDetail | varchar(255) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
mysql> desc person_senior_inf;
+-----------+--------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+-------+
| person_id | int(11) | NO | PRI | NULL | |
| name | varchar(255) | NO | | NULL | |
| age | int(11) | YES | | NULL | |
+-----------+--------------+------+-----+---------+-------+
此种方式导致 新建一个person后,其对应的address无法更新?
配置:
<!-- 主键 单向1-1关联 -->
<id name="id" column="person_id">
<!-- 主键生成策略是foreign,表示根据关联类的主键来生成该实体的主键 -->
<generator class="foreign">
<param name="property">address</param>
</generator>
</id>
<!-- 下面映射基于主键的1-1关联 -->
<one-to-one name="address" />
3. 单向1-N关联
持久化类里需要使用集合属性,而这个集合属性数据来自其他的表,且该表已经有映射的对象了.
(与之前的映射集合元素不一样,之前是使用element,且没有映射对象.,比如之前没有Address这个类),
这里element改成one-to-many
3.1 无连接表的单向1-N
<!-- 无连接表的单向 1-N -->
<set name="allAddress" >
<key column="person_id"/>
<one-to-many class="Address" />
</set>
//创建新地址
Address address2 = new Address("三山街");
Address address3 = new Address("夫子庙");
session.persist(address2);//这里需要先持久化否则后面add会报错
session.persist(address3);
aGuy.getAllAddress().add(address2);
aGuy.getAllAddress().add(address3);
mysql> desc address_inf;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| address_id | int(11) | NO | PRI | NULL | auto_increment |
| addressDetail | varchar(255) | YES | | NULL | |
| person_id | int(11) | YES | MUL | NULL | |
+---------------+--------------+------+-----+---------+----------------+
mysql> desc person_senior_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| person_id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| age | int(11) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
一个person对应N个address
mysql> select * from address_inf;
+------------+---------------+-----------+
| address_id | addressDetail | person_id |
+------------+---------------+-----------+
| 1 | 新街口 | NULL |
| 2 | 三山街 | 1 |
| 3 | 夫子庙 | 1 |
+------------+---------------+-----------+
3.2 有连接表的单向1-N关联
<!-- 有连接表的单向 1-N 使用 many-to-many,但需要设置unique="true" -->
<set name="allAddress" table="person_address">
<key column="person_id"/>
<many-to-many class="Address" column="address_id" unique="true"/>
</set>
mysql> desc address_inf;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| address_id | int(11) | NO | PRI | NULL | auto_increment |
| addressDetail | varchar(255) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
mysql> desc person_senior_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| person_id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| age | int(11) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
mysql> desc person_address;
+------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| person_id | int(11) | NO | PRI | NULL | |
| address_id | int(11) | NO | PRI | NULL | |
+------------+---------+------+-----+---------+-------+
4. 单向N-N关联
和有连接的单向1-N关联类似,配置时去掉many-to-many的unique=true
<!-- 单向N-N关联 -->
<set name="allAddress" table="person_address">
<key column="person_id"/>
<many-to-many class="Address" column="address_id"/>
</set>
mysql> desc address_inf;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| address_id | int(11) | NO | PRI | NULL | auto_increment |
| addressDetail | varchar(255) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
mysql> desc person_senior_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| person_id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| age | int(11) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
mysql> desc person_address;
+------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| person_id | int(11) | NO | PRI | NULL | |
| address_id | int(11) | NO | PRI | NULL | |
+------------+---------+------+-----+---------+-------+
5. 双向1-N管理
5.1 无连接表的双向1-N关联
N端需要修改<many-to-one>,1的一段需要增加<set>,<set>里面增加
<key>子元素映射外键,并使用<one-to-many>子元素映射关联属性.
<!-- 无连接表 双向1-N关联,1的那端 -->
<set name="allAddressWithPerson" inverse="true">
<key column="person_id"/>
<one-to-many class="AddressWithPerson"/>
</set>
<!-- 无连接表 双向1-N关联,N 的那端 -->
<!-- 必须指定列名为person_id,与关联实体中key元素的column值相同 -->
<many-to-one name="person" class="Person" column="person_id" not-null="true" />
mysql> desc address_inf;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| address_id | int(11) | NO | PRI | NULL | auto_increment |
| addressDetail | varchar(255) | YES | | NULL | |
| person_id | int(11) | NO | MUL | NULL | |
+---------------+--------------+------+-----+---------+----------------+
mysql> desc person_senior_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| person_id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| age | int(11) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
因为N的那端已经有了1端的引用,所有在Java代码中的步骤如下(P446):
(1) 创建一个1端实例,并持久化
(2) 创建一个N端的实例,使用set方法将(1) 中实例set进来
(3) 持久化(2)中N端实例
public void test()
{
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
Person aGuy = new Person();
aGuy.setName("Frank");
aGuy.setAge(28);
//持久化1端实例
session.save(aGuy);
//创建N端实例
AddressWithPerson addressWithPerson1 = new AddressWithPerson("新街口 with person");
addressWithPerson1.setPerson(aGuy);
//这里表示通过N端对象来设置关联关系,因为在1端配置了,inverse="true"
//表示不能用Person的Set的add方法设置关联关系了.
session.persist(addressWithPerson1);
tx.commit();
HibernateUtil.closeSession();
}
5.2 有 连接表的双向1-N关联
有 连接表 的双向1-N,1端使用set,N端,相当于N-1,使用join.
<!-- 有连接表的 双向1-N关联 1的那端 -->
<set name="allAddressWithPerson" inverse="true" table="person_address">
<key column="person_id"/>
<many-to-many class="AddressWithPerson" column="address_id" unique="true" />
</set>
<!-- 有 连接表 的 双向1-N关联 N的那端 -->
<join table="table_address">
<key column="address_id" />
<many-to-one name="person" column="person_id" not-null="true" />
</join>
mysql> desc address_inf;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| address_id | int(11) | NO | PRI | NULL | auto_increment |
| addressDetail | varchar(255) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
2 rows in set (0.02 sec)
mysql> desc person_senior_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| person_id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| age | int(11) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> desc person_address;
+------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| address_id | int(11) | NO | PRI | NULL | |
| person_id | int(11) | NO | MUL | NULL | |
+------------+---------+------+-----+---------+-------+
mysql> select * from person_address;
+------------+-----------+
| address_id | person_id |
+------------+-----------+
| 1 | 1 |
| 2 | 1 |
+------------+-----------+
2 rows in set (0.00 sec)
6. 双向 N-N关联
双向N - N 关联需要在两端都使用set集合.双向N - N关联只能采用连接表
<!-- 双向N-N关联 只能采用连接表 -->
<set name="allAddressWithPerson" table="person_address">
<key column="person_id"/>
<many-to-many class="AddressWithPerson" column="address_id" />
</set>
<!-- 双向N-N关联 只能采用连接表 -->
<set name="persons" table="person_address">
<key column="address_id"/>
<many-to-many class="Person" column="person_id" />
</set>
mysql> desc address_inf;
+---------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+--------------+------+-----+---------+----------------+
| address_id | int(11) | NO | PRI | NULL | auto_increment |
| addressDetail | varchar(255) | YES | | NULL | |
+---------------+--------------+------+-----+---------+----------------+
mysql> desc person_senior_inf;
+-----------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+--------------+------+-----+---------+----------------+
| person_id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(255) | NO | | NULL | |
| age | int(11) | YES | | NULL | |
+-----------+--------------+------+-----+---------+----------------+
mysql> desc person_address;
+------------+---------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------+---------+------+-----+---------+-------+
| person_id | int(11) | NO | PRI | NULL | |
| address_id | int(11) | NO | PRI | NULL | |
+------------+---------+------+-----+---------+-------+
双向N-N时,在两个id上创建联合主键:primary key (address_id, person_id)
7. 双向1-1关联
修改两个类,存放对对方的引用,并加上getter和setter
7.1 基于外键的双向 1-1关联
<!-- 基于外键的 双向 1-1 关联 person端-->
<one-to-one name="addressWithPerson" property-ref="person" />
<!-- 基于外键的 双向 1-1 关联 address端-->
<many-to-one name="person" unique="true" column="person_id" not-null="true" />
以下略.(P450)
7.2 基于主键的 双向 1-1 关联(P451)
7.3 有连接表的双向1-1关联(P452)
相关推荐
hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,包含4个说明文档,分别详细解说了hibernate关联映射的...
本文将深入探讨“hibernate关联映射实例”中的关键知识点,包括一对多、多对多和继承映射,这些都是Hibernate中至关重要的概念。 1. **一对多关联映射**: 在现实世界中,一个实体可能会与多个其他实体相关联,...
### Hibernate关联映射的作用与常用属性详解 #### 关联映射概述 在对象关系映射(Object Relational Mapping,简称ORM)技术中,Hibernate作为Java领域内非常成熟且功能强大的框架之一,它允许开发者将Java类映射...
### Hibernate关联映射总结 #### 一、基础知识 在探讨Hibernate中的关联映射之前,我们需要先理解几个基本概念,这将有助于我们更好地理解和应用这些关联映射。 - **主键**(Primary Key):主键是用来唯一标识一...
在 Hibernate 映射中,需要使用 `one-to-one` 元素,并设置 `constrained="true"`,表明该类的主键由关联类生成。 3. Hibernate 一对一连接表单向关联: 这种关联方式是通过额外的连接表来实现一对一关系的。连接...
本教程“Hibernate关联映射.rar”聚焦于Hibernate中的关联映射,特别是多对一和一对多的关系映射,非常适合初学者了解和实践。 首先,我们要理解什么是关联映射。在数据库中,表与表之间存在各种关系,如一对一、一...
总的来说,这个压缩包提供了丰富的Hibernate关联映射的学习资源,涵盖了从基础到进阶的各种关联类型。通过学习这些示例,你将能够熟练掌握如何在Java项目中使用Hibernate进行数据持久化,并灵活地处理各种数据库关系...
本文将深入探讨“Hibernate关联映射中的Many-to-One关系”。 Many-to-One关联是现实世界中常见的关系类型,比如一个学生可以对应多个课程,而一个课程可能被多个学生选修。在数据库中,这通常表现为一对多(One-to-...
hibernate关联映射是Hibernate框架中的一个重要概念,它用于在Java对象模型和数据库表之间建立关系,使得数据操作更加方便。以下将详细介绍各种类型的关联映射: 1. **单向N-1关联(无连接表)** 在这种关联中,一...
在Java的持久化框架Hibernate中,关联映射是至关重要的概念,它允许我们将数据库中的表关系映射到对象之间的关系。SSH(Struts、Spring、Hibernate)是经典的Java Web开发框架,其中Hibernate负责数据访问层,提供了...
本话题主要探讨的是Hibernate中的一种关联映射方式——一对一(One-to-One)单向外键关联。这种关联模式通常用于两个实体之间存在唯一对应的关系,例如一个用户对应一个唯一的账户。 在Hibernate中,一对一关联可以...
本篇文章将深入探讨Hibernate中的关联映射,特别是One-to-One(一对一)关联,这是一种表示两个实体之间一对一关系的映射方式。我们将通过源码分析和实际例子来理解其工作原理。 ### 一、One-to-One关联概述 在...
在Java的持久化框架Hibernate中,关联映射是核心特性之一,它允许我们将数据库中的表关系映射到对象之间的关系。本篇将深入探讨一种特殊的关联映射方式——一对一(One to One)映射,特别是在双向关联的情况下的...
在Java的持久化框架Hibernate中,一对一(One-to-One)关联映射是一种常见的关系数据库模型映射方式。这种关联通常发生在两个实体之间,且每个实体都只有一个对应的实例。本篇文章将详细探讨双向一对一主键关联映射...