Hibernate--关联映射

       hibernate是持久层ORM框架,关系映射解决了对象型实体与关系型数据库不相匹配的问题,它是Hibernate的核心内容,在实际操作中我们必须要根据数据表的相互关系,根据业务需求,建立相互适应的关系映射,这样才能提高开发效率和系统运行效率。


关系映射主要包括以下:

                                             

          关系型映射分为单向和双向映射两种,上图中除了继承和component映射均可以建立单向和双向两种映射方式。而且1:N这种映射如果建立单向映射就会存在很多问题,让我们来分析一下各个映射应用场景的实现方式。


    (1)多对一映射

                                                        

       如上图,User和Group属于N:1映射,单向的多对一映射,要求我们访问User时能够找到对应的Group,所以考虑在多的一方t_user添加groupid,通过维护grouid来维护user与Group之间的关系,在代码实现过程中,User类中添加Group类的引用,xml配置gruopid:

<class name="User" table="t_user">
    <id name="id">
        <generator class="native"/>
     </id>
      <property name="name"/>
      <many-to-one name="group" column="groupId" not-null="true">
</class>

     (2) 一对一映射

          

             一对一关系映射分为主键关联映射和唯一外键关联映射两种,主键关联映射通过共享主键的方式,不需要添加维护字段,靠主键相等来维护数据表关系。

                                                               

        单向映射,只需要在Person中添加IdCard的引用,其xml映射文件如下:

		<class name="com.whp.hibernate.Person" table="t_table">
			<id name="id">
				<generator class="foreign">
					<param name="property">idCard</param>
				</generator>
			</id>
			<property name="name"/>
			
			<one-to-one name="idCard" constrained="true"/>  <!--constrained为约束-->
		</class>

           双向映射,则需要在IdCard中添加person引用:

		<class name="com.whp.hibernate.IdCard" table="t_idcard">
			<id name="id">
				<generator class="native"/>
			</id>
			<property name="name"/>
			<one-to-one name="person"/>
		</class>

    一对一外键关联映射在一方添加维护字段,使其保持唯一性,与对应一方建立唯一数据联系。对比于主键关联映射,它更具有扩展性,可以随时更改为多对一关系。

	<class name="com.whp.hibernate.Person" table="t_pserson">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<many-to-one name="idCard" unique="true"/>
	</class>


     双向映射则必须保持映射字段统一,使用property-ref属性来限制:

	<class name="com.whp.hibernate.IdCard" table="t_idcard">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="cardNo"/>
		<one-to-one name="person" property-ref="idCard"/>
	</class>


     (3)一对多关系


       上面有提到一对多映射存在很多问题,我们从其映射图来分析:

                

    在单向的多对一关系映射中,班级属于一,当插入classes中字段时,首先插入其基本属性的数据,然后通过大量的更新语句来更新student实体,这样如果一个班级的学生人数很多的情况下,班级表的插入语句将引发大量的update语句造成执行效率下降。单纯由classes来维护关系,student实体将不知道自己对应的哪个班级,因此多数情况下的一对多关系都是双向关联映射。


    好的实现方式是在一的一端加入set,由多的一端维护关系:

	<class name="com.whp.hibernate.Classes" table="t_classes">
		<id name="id">
			<generator class="native"/>
		</id>
		
		<property name="name"/>
		<set name="students" inverse="true">
			<key clomun="classesid"/>
			<one-to-many class="com.whp.hibernate.Student"/>
		</set>
	</class>
	<class name="com.whp.hibernate.Student" table="t_student">
		<id name="id">
			<generator class="native"/>
		</id>
		
		<property name="name"/>
		<many-to-one name="classes" column="classesid"/>
	</class>

    由上面实现过程,Classes的set属性中添加inverse="true"属性让出控制权,让控制反转,交给student来维护关系。


    (4)多对多关系


     多对多关系则需要抽象出第三张维护表来维护关系

	<class name="com.whp.hibernate.User" table="t_user">
			<id name="id">
				<generator class="native"/>
			</id>
			
			<property name="name"/>
			<set name="roles" table="t_user_role">
				<key column="user_id"/>
				<many-to-many class="com.whp.hibernate.Role" column="role_id"/>
			</set>
	</class>

    (5)继承映射


    继承映射通常有两种方式实现,第一种是在同一张表中添加各个子类的冗余字段和标识字段;第二种方式是建立多张表与维护字段。第一种方式通过一张表维护,执行效率高,但存在冗余字段,且这些冗余字段必须允许为空;第二种方式该类必须实现序列化,只有这样才能让数据跨网络传输,将数据保存到本地,尤其在分布式系统应用中极为重要。


    第一种方式实现方式:

                  

		<class name="Animal" table="t_animal" lazy="false">
				<id name="id">
					<generator class="native"/>
				</id>
				
				
				<discriminator column="type" type="string"/>
				<property name="name"/>
				<property name="sex"/>
		
				<subclass name="Pig" discriminator-value="P">
					<property name="weight"/>
				</subclass>
				
				<subclass name="Bird" discriminator-value="B">
					<property name="height"/>
				</subclass>
		</class>
		

     (6)component映射

                   

     component映射属于细粒度划分,提高复用率,如上图中抽出公共属性部分放入Contact中,可以分别组合User和Employee。

       <class name="com.bjpowernode.hibernate.Employee" table="t_emplyee">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<component name="employeeContact">
			<property name="email"/>
			<property name="address"/>
			<property name="zipCode"/>
			<property name="contactTel"/>
		</component>
	</class>

      <class name="com.bjpowernode.hibernate.User" table="t_user">
		<id name="id">
			<generator class="native"/>
		</id>
		<property name="name"/>
		<component name="userContact">
			<property name="email"/>
			<property name="address"/>
			<property name="zipCode"/>
			<property name="contactTel"/>
		</component>
	</class>





评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值