您的位置:首页 > 其它

Hibernate(六):实体关系映射

2017-08-08 14:21 369 查看
   

 

   从图上可以看出映射的分类与关系。 

     基本映射就是对一个实体进行映射。关系映射就是出来多个实体之间的关系,将关联关系映射到数据库中。所谓的关联关系就是对象模型中有一个或多个的引用。

  关系映射就分为以下的七种:

1,多对一关联(单向)

映射原理:单向 n-1 关联只需从 n 的一端可以访问 1 的一端,既在多的一端持有一的一端的引用

实例:Product和Factory之间的关系(多个商品对应一家生产厂)。在Product的映射文件张建立多对一的关系



<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

<class name="com.Product" table="product">
<!-- id值 -->
<id name="id" column="id" type="int">
<generator class="native"/>
</id>
<!-- 产品名称 -->
<property name="name" type="string" length="45">
<column name="name"/>
</property>
<!-- 产品价格 -->
<property name="price" type="double">
<column name="price"/>
</property>
<!-- 多对一关联映射 -->
<many-to-one name="factory" class="com.mr.factory.Factory">
<!-- 映射的字段 -->
<column name="factoryid"/>
</many-to-one>
</class>
</hibernate-mapping>
<many-to-one>元素:定义一个持久化类与另一个持久化类的关联,这种关联就是数据表之间的多对一关联,需要此持久化类映射表的外键引用另一个持久化类映射表的主键,也就是映射的字段。

   name:持久化类中的的属性
    column: 设定和持久化类的属性对应的表的外键   
   class:关联的目标持久化类

2.一对多关联(单向)

 一对多和多对一的映射原理是一致的,存储是相同的,也就是生成的数据库之间的表时一样的。不同的是他们之间的维护关系。

       多对一的维护关系:多指向一的关系,有了此关系,加载多的时候可以将一加载上来

     一对多的维护关系:一指向多的关系,有了此关系,夹杂一的时候可以将多加载上来     

3.一对多关联(双向)






映射原理: Hibernate既可以通过主控方实体加载被控方实体,也可以通过被控方加载对应的主控方实体

实例:由于一个生产商可以对应多件产品,在Factory类中以集合的形式引入Product对象,在映射文件中通过<set>标签进行映射

Factory的映射文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 产品信息字段配置信息 -->
<hibernate-mapping>
<class name="com.mr.factory.Factory" table="tab_factory">
<!-- id值 -->
<id name="factoryId" column="factoryid" type="int">
<generator class="native"/>
</id>
<!-- 生产商名称 -->
<property name="factoryName" type="string" length="45">
<column name="factoryname"/>
</property>
<!-- 定义一对多映射 -->
<set name="products"
inverse="true"
>
<key column="factoryid"/>
<one-to-many class="com.mr.product.Product"/>
</set>
</class>
</hibernate-mapping>


<set> 元素来映射持久化类的 set 类型的属性

 name: 设定待映射的持久化类的属性的
 inverse:决定是由双向关联的的哪一方来维护表与表之间的关系,false的为主动方, true为被动方,由主动方负责维护关系。(在多对一的关系中,如果将“一”设为主动方:会额外的多出update语句,插入数据时无法同时插入外键列)。这个属性只影响数据的存储
order-by:如果设置该属性,当Hibernate通过select语句到数据库检索集合对象时,利用order by语句进行排序        

<key> 元素设定与所关联的持久化类对应的表的外键

column: 指定关联表的外键名

注意

  当 Session 从数据库中加载 Java 集合时, 创建的是 Hibernate 内置集合类的实例, 因此在持久化类中定义集合属性时必须把属性声明为 Java 接口类型

 Hibernate 的内置集合类具有集合代理功能, 支持延迟检索策略
 事实上, Hibernate 的内置集合类封装了 JDK 中的集合类, 这使得 Hibernate 能够对缓存中的集合对象进行脏检查, 按照集合对象的状态来同步更新数据库。 

 在定义集合属性时, 通常把它初始化为集合实现类的一个实例. 这样可以提高程序的健壮性, 避免应用程序访问取值为 null 的集合的方法抛出 NullPointerException

代码:

public class Factory {

private Integer factoryId;//生产商的id
private String factoryName;//生产商名称
private Set<Product> products;//Set集合,一个厂商所对应的所有图书
.....
}


4.一对一主键关联

   映射原理: 一对一主键关联是指两个表之间通过主键形成一对一的映射(两个实体对象是一对一的关联映射)。

   基于主键的映射策略:指一端的主键生成器使用foreign策略,表明根据“对方”的主键来生成自己的主键,自己并不能独立生成主键

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

实例:每个公民只允许拥有一个身份证,公民与身份证就是一对一关系。定义两个数据表,分别有两个表people(公民表)和idcard(身份证表)。其中的people中的id既是该表的主键和外键。



people的映射文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 公民信息字段配置信息 -->
<hibernate-mapping>
<class name="com.mr.people.People" table="tab_people">
<!-- id值 -->
<id name="id" column="id" type="int">
<generator class="native"/>
</id>
<!-- 公民姓名 -->
<property name="name" type="string" length="45">
<column name="name"/>
4000
;
</property>
<!-- 公民性别 -->
<property name="sex" type="string" length="2">
<column name="sex"/>
</property>
<!-- 公民年龄 -->
<property name="age" type="int">
<column name="age"/>
</property>
<!-- 一对一映射 -->
<one-to-one name="idcard" class="com.mr.idcard.IDcard"
cascade="all"/>
</class>
</hibernate-mapping>
idcard的映射文件:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 <!-- 公民身份证字段信息配置信息 -->
 <hibernate-mapping>
 	<class name="com.mr.idcard.IDcard" table="tab_idcard">
 		<!-- id值 -->
 		<id name="id" column="id" type="int">
<!-- 外键生成 -->
<generator class="foreign">
<param name="property">people</param>
</generator>
</id>
<!-- 公民身份证号 -->
<property name="idcard_code" type="string" length="45" not-null="true">
<column name="IDcard_code"/>
</property>
                <one-to-one name="com.mr.people.People    //一对一映射
                   constrained="true"/>
             
 	</class>
 </hibernate-mapping>

cascade(级联)操作是指当主控方执行save,update或delete操作时,关联对象(被控方)是否进行同步操作。在映射文件中使用cascade属性进行操作

在对象 – 关系映射文件中, 用于映射持久化类之间关联关系的元素, <set>, <many-to-one> 和 <one-to-one> 都有一个 cascade 属性, 它用于指定如何操纵与当前对象关联的其他对象. 



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

一对一主键关联的缺点:

 灵活性差,没有办法改成多对一的关联映射,不能应变多变的需求
 必须先保存关联对象idcard,才能保存people

一般,在映射一对一单行关联映射时采用外键关联映射

5.一对一外键关联

基于外键的一对一关联,其外键可以存放在任意一端,在需要存放外键一端,增减many-to-one元素,为其添加unique="true”属性来表示1-1关联

实例:用身份证实例对象和公民实例对象为例。在people表添加一个新的字段card_id,作为该表的外键,同时需要保证该字段的唯一性



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- 公民信息字段配置信息 -->
<hibernate-mapping>
<class name="com.mr.people.People" table="tab_people">
<!-- id值 -->
<id name="id" column="id" type="int">
<generator class="native"/>
</id>
<!-- 公民姓名 -->
<property name="name" type="string" length="45">
<column name="name"/>
</property>
<!-- 公民性别 -->
<property name="sex" type="string" length="2">
<column name="sex"/>
</property>
<!-- 公民年龄 -->
<property name="age" type="int">
<column name="age"/>
</property>
<!-- 一对一映射 -->
<many-to-one name="idcard" unique="true">
<column name="card_id"/>
</many-to-one>
</class>
</hibernate-mapping>

上面讲的一对一的主键和外键关联映射,下来是双向的关联映射

双向关联映射原理:原理和单向的映射相同,只不过是可以从两端加载另一端。双向关联映射并不影响存储,只影响加载。双向关联映射和单向关联映射的数据库表的结构相同。只需要在另一端实体对象的映射文件中加入对另一个的引用,主键关联和外键关联的使用如上。

6.多对多关联(单向)

与一对一和多对一关联联系不同,需要通过另外一张表保存多对多的映射关系 。与一对多的映射类似,必须为set集合元素添加key子元素。与一对多映射不同的是,集合的中的元素使用的是many-to-many。

<many-to-many>元素:

class:指定集合存放的对象

7.多对多关联(双向)

和单向相同的是:使用连接表,集合属性添加key元素用于映射外键列,集合元素里添加<many-to-many>子元素关联实体类 

双向关联需要两端使用集合属性

<set>集合属性:

 在双向关联的两边都需要指定连接表的表名及外键列的表名。
 两个集合元素的set的table值必须指定,并且相同。
 set元素中的两个子元素:key和many-to-many都必须指定column属性。key和column分别指定的 是本持久化类和关联类在连接表中的外键列名。因此,两边的两个属性交叉  相同
 必须把其中的一端的inverse设置为true,否则两端都维护关联关系可能会造成主键冲突

实例:应用系统的权限分配:用户可以有多个系统的操作权限,一个权限又可以赋给多个用户。



由于是多对多的关系,所以实体对象User和Role是相互引用的关系,需要在实体对象中引入Set集合。

Role

public class Role {
private Integer id;//唯一性标识
private String roleName;//权限名称
private Set<User> users;//引用的用户实体对象集合
....
}User
public class User {
private Integer id;//唯一性标识
private String name;//用户名称
private Set<Role> roles;//引用的权限实体对象集合
....
}

User.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- User实体对象 -->
<hibernate-mapping>
<class name="com.mr.user.User" table="tab_user">
<!-- 主键id -->
<id name="id">
<generator class="native"/>
</id>
<!-- 用户名称 -->
<property name="name" not-null="true" />
<set name="roles" table="tab_mapping">
<key column="user_id"></key>
<many-to-many class="com.mr.role.Role" column="role_id"/>
</set>
</class>
</hibernate-mapping>


Role.hbm.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Role实体对象 -->
<hibernate-mapping>
<class name="com.mr.role.Role" table="tab_role">
<!-- 主键id -->
<id name="id">
<generator class="native"/>
</id>
<!-- 权限名称 -->
<property name="roleName" not-null="true">
<column name="rolename"/>
</property>
<set name="users" table="tab_mapping">
<key column="role_id"></key>
<many-to-many class="com.mr.user.User" column="user_id"/>
</set>
</class>
</hibernate-mapping>可以从两个实体对象的的映射文件得出:两个之间连接表为tab_mapping
总结:

    (1)从对象的加载方式看,关系映射分为两种:单向和双向。单向和双向只影响数据的加载,而不是数据的存储。生成的数据库的表是相同的。它们的不同是由对象模型决定的

    (2)从对象的映射关系来看,分为四种:一对一的,一对多,和多对一和多对多的。不同是每个在两端的限制不同
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  关系映射