- 单向 n-1
- 双向1-n
- 多对多(双向)
- 基于外键的1对1
- 基于主键的1对1
单向 n-1
以Customer 与 Order做例子,一个Customer有对应多个Order,但多个Order没有对应一个Customer。
此时,在持久化类中,多的一端即Order这端,有对Customer的引用(即有Cutomer的对象)。
在关系数据模型中,ORDERS表中的CUSTOMER_ID 参照CUSTOMER表的主键。
在配置文件中,
Customer:
<hibernate-mapping>
<class name="com.hibernate.helloworld.n21.Customer" table="CUSTOMERS">
<id name="id" type="java.lang.Integer" >
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String" >
<column name="NAME" />
</property>
</class>
</hibernate-mapping>
Order:
<hibernate-mapping package="com.hibernate.helloworld.n21">
<class name="Dingdan" table="DINGDAN">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id>
<!--
映射多对一的关联关系。 使用 many-to-one 来映射多对一的关联关系
name: 多这一端关联的一那一端的属性的名字,即多端的持久化类的对象
class: 一那一端的属性对应的类名,即参照表的持久化类名
column: 一那一端在多的一端对应的数据表中的外键的名字
-->
<many-to-one name="customer" class="Customer" >
<column name="CUSTOMER_ID" />
</many-to-one>
</class>
</hibernate-mapping>
双向1-n:
双向 1-n 需要在1的一端可以访问n 的一端,反之亦然。在域模型中,在多的一端即Order类中定义一个Customer的属性,在1的一端即Customer类中定义存放Order 对象的集合属性。
在关系数据模型中,ORDERS表中的CUSTOMER_ID 参照CUSTOMER 表的主键。
配置文件:
Customer:
<hibernate-mapping package="com.hibernate.helloworld.n21.both">
<class name="Customer" table="CUSTOMERS">
<id name="id" type="java.lang.Integer" >
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String" >
<column name="NAME" />
</property>
<!-- 映射 1 对多的那个集合属性 -->
<!-- set: 映射 set 类型的属性, table: set 中的元素对应的记录放在哪一个数据表中. 该值需要和多对一的多的那个表的名字一致 -->
<!-- inverse: 指定由哪一方来维护关联关系. 通常设置为 true, 以指定由多的一端来维护关联关系 -->
<!-- cascade 设定级联操作. 开发时不建议设定该属性. 建议使用手工的方式来处理 -->
<!-- order-by 在查询时对集合中的元素进行排序, order-by 中使用的是表的字段名, 而不是持久化类的属性名 -->
<set name="dingdans" table="DINGDAN" inverse ="true">
<key column="CUSTOMER_ID"></key>
<one-to-many class="Ding"/>
</set>
</class>
</hibernate-mapping>
Order配置文件与单向n-1 一致,不再详述。
双向多对多
以类别Category 和商品Item 做例子。
双向n-n 必须使用连接表即中间表,其关联需要两端都使用集合属性。
两个集合元素 set 的 table 元素的值必须指定且相同,set元素的两个子元素:key 和many-to-many 分别指定本持久化类和关联类在连接表中的外键列名,所以两边的key和many-to-many 的column 值属性交叉相同。
注意:对于双向 n-n 关联,必须把其中一端的inverse 设置为true,表示只做一端维护。
配置文件(只写关键配置信息):
Category :
<!-- table 指定中间表名称 -->
<set name="items" table="CATEGORIES_ITEMS" inverse="true">
<key column="C_ID"></key>
<!-- 使用many-to-many 指定多对多的关联关系。
column 指定Set 集合中的持久化类在中间表的外键列的名称 -->
<many-to-many class="Item" column="I_ID"></many-to-many>
</set>
Item:
<!-- 中间表必须一致 ,table为指定中间表名-->
<set name="categories" table="CATEGORIES_ITEMS">
<!-- 当前持久化类在中间表中的外键列id -->
<key column = "I_ID"></key>
<many-to-many column="C_ID" class="Category"></many-to-many>
</set>
1对1映射
以一个部门Department 对应一个经理Manager为例子
基于外键的1对1映射
按照外键映射,即以在一张表中定义外键映射另一张表的主键。
此例子以Depatment为定义外键的表,在存放外键表的配置文件中需增加unique=”true”属性表述为1-1关联。
在one-to-one元素的配置中需增加 property-ref 属性指定使用被关联实体主键以外的字段作为关联字段。即与many-to-one元素的name属性值相同。
在两个持久化类都有对对方的对象属性。
Department 配置文件:
<many-to-one name="mgr" class="Manager"
column="MGR_ID" unique="true"></many-to-one>
Manager 配置文件:
<one-to-one name="dept" class="Department"
property-ref="mgr"></one-to-one>
基于主键的1对1映射
持久化类与基于外键的1对1映射的持久化类一致,无需更改。
Department 的配置文件:
<!-- 使用外键的方式来生成当前的主键 -->
<generator class="foreign">
<!--property 属性指定使用当前持久化类的哪一个属性的主键作为外键 -->
<param name="property">mgr</param>
</generator>
<!--
采用foreign 主键生成器策略的一端增加 one-to-one 元素映射关联属性,
其one-to-obe 节点还应增加constraioned="true" 属性,以使当前的主键添加外键约束
-->
<one-to-one name="mgr" class="Manager" constrained="true"></ont-to-one>
Manager 的配置文件:
<one-to-one name="dept" class="DepartMent"></one-to-one>