`

Hibernate 关联映射

 
阅读更多

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,hibernate,包含4个说明文档,分别详细解说了hibernate关联映射的...

    hibernate关联映射实例

    本文将深入探讨“hibernate关联映射实例”中的关键知识点,包括一对多、多对多和继承映射,这些都是Hibernate中至关重要的概念。 1. **一对多关联映射**: 在现实世界中,一个实体可能会与多个其他实体相关联,...

    hibernate关联映射的作用和常用属性解释

    ### Hibernate关联映射的作用与常用属性详解 #### 关联映射概述 在对象关系映射(Object Relational Mapping,简称ORM)技术中,Hibernate作为Java领域内非常成熟且功能强大的框架之一,它允许开发者将Java类映射...

    Hibernate关联映射

    在 Hibernate 映射中,需要使用 `one-to-one` 元素,并设置 `constrained="true"`,表明该类的主键由关联类生成。 3. Hibernate 一对一连接表单向关联: 这种关联方式是通过额外的连接表来实现一对一关系的。连接...

    Hibernate关联映射.rar

    本教程“Hibernate关联映射.rar”聚焦于Hibernate中的关联映射,特别是多对一和一对多的关系映射,非常适合初学者了解和实践。 首先,我们要理解什么是关联映射。在数据库中,表与表之间存在各种关系,如一对一、一...

    hibernate 全面学习->hibernate 关联映射学习

    总的来说,这个压缩包提供了丰富的Hibernate关联映射的学习资源,涵盖了从基础到进阶的各种关联类型。通过学习这些示例,你将能够熟练掌握如何在Java项目中使用Hibernate进行数据持久化,并灵活地处理各种数据库关系...

    hibernate 关联映射(一) many to one

    本文将深入探讨“Hibernate关联映射中的Many-to-One关系”。 Many-to-One关联是现实世界中常见的关系类型,比如一个学生可以对应多个课程,而一个课程可能被多个学生选修。在数据库中,这通常表现为一对多(One-to-...

    hibernate关联映射

    hibernate关联映射是Hibernate框架中的一个重要概念,它用于在Java对象模型和数据库表之间建立关系,使得数据操作更加方便。以下将详细介绍各种类型的关联映射: 1. **单向N-1关联(无连接表)** 在这种关联中,一...

    hibernate关联映射详解SSH 多对多,一对多关系对象映射

    在Java的持久化框架Hibernate中,关联映射是至关重要的概念,它允许我们将数据库中的表关系映射到对象之间的关系。SSH(Struts、Spring、Hibernate)是经典的Java Web开发框架,其中Hibernate负责数据访问层,提供了...

    Hibernate关联映射-one to one单向外键关联

    本话题主要探讨的是Hibernate中的一种关联映射方式——一对一(One-to-One)单向外键关联。这种关联模式通常用于两个实体之间存在唯一对应的关系,例如一个用户对应一个唯一的账户。 在Hibernate中,一对一关联可以...

    hibernate 关联映射(二) one to one(单向)

    本篇文章将深入探讨Hibernate中的关联映射,特别是One-to-One(一对一)关联,这是一种表示两个实体之间一对一关系的映射方式。我们将通过源码分析和实际例子来理解其工作原理。 ### 一、One-to-One关联概述 在...

    hibernate 关联映射(三) one to one(双向)

    在Java的持久化框架Hibernate中,关联映射是核心特性之一,它允许我们将数据库中的表关系映射到对象之间的关系。本篇将深入探讨一种特殊的关联映射方式——一对一(One to One)映射,特别是在双向关联的情况下的...

    Hibernate一对一主键关联映射(双向关联)

    在Java的持久化框架Hibernate中,一对一(One-to-One)关联映射是一种常见的关系数据库模型映射方式。这种关联通常发生在两个实体之间,且每个实体都只有一个对应的实例。本篇文章将详细探讨双向一对一主键关联映射...

Global site tag (gtag.js) - Google Analytics