Hibernate详解(2)——一对多映射分析

点击上面  免费订阅本账号!

本公众号主要推送javaweb开发相关技术,基础知识点,同时会深入剖析复杂的问题,分享一些优秀的框架,大型项目经验,当今最流行的Javaweb技术,热点科技新闻,招聘信息,生活乐趣等等。点击上方的蓝字,这样您每天可以看到更多的java知识和资讯!完全是免费订阅,请放心关注。

在学习Hibernate的时候,很大一部分任务量是配置实体映射关系,hibernate的映射关系的关键就是掌握面向对象的思想,搞清楚实体之间的关系。每一个实体关系都对应这UML中的对象关系。我们配置这些对象的关系模型。下面分节讲述Hibernate的关系映射。

 

本节主要讲述Hibernate的一和多的关系。之所以称之为一和多的关系,是因为他包括三种关系:单向一对多,单向多对一,双向一对多。我这里统称为它一对多。一对多关系是非常重要的关系,也是现实世界中最多的关系。这三个关系对应的是UML中的关联关系,也可以分成聚合和组合。

 

之所以把一对多分成三种类型,是因为它们站的角度不同。这里就拿学生和班级的关系举例,站在学生的角度看这个关系是多对一,站在班级的角度看是一对多。但是为了更好的使用这个关系,也考虑到实际操作的原因。一般把它们设置成双向一对多。

 

单向多对一


单向多对一是站在多的角度去看关系的,在本例中就是站在学生的角度去看。首先看这个关系的UML图。


多个学生对应一个班级。这里的关系就是多对一的关系,站在学生的角度看。如果我们只是需要知道学生位于那个班级。这样就只是单向的关系,也就是拿到Studenthibernate会自动的给你抓取到对应的Classes。单向的多对一是由需求产生的。是人为的设定的。这样的关系中,Studnet一端负责维护关系。它的映射原理是在Studnet表的一段加入外键,指向一的一端。

下面看这两个实体对应的配置文件Student.hbm.xmlClasses.hbm.xml

[html] view plain copy

  1. <?xmlversionxmlversion="1.0"?>  

  2. <!DOCTYPEhibernate-mapping PUBLIC  

  3. "-//Hibernate/HibernateMapping DTD 3.0//EN"  

  4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  

  5. <hibernate-mapping>  

  6. <classnameclassname="com.lsh.hibernate.Classes" table="t_class">  

  7. <idnameidname="id">  

  8. <generatorclassgeneratorclass="native"/>  

  9. </id>  

  10. <propertynamepropertyname="name"/>  

  11. </class>  

  12. </hibernate-mapping>  

关系在多的一端维护,就在多的一端配置。

[html] view plain copy

  1. <?xmlversionxmlversion="1.0"?>  

  2. <!DOCTYPEhibernate-mapping PUBLIC  

  3. "-//Hibernate/HibernateMapping DTD 3.0//EN"  

  4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  

  5. <hibernate-mapping>  

  6. <classnameclassname="com.lsh.hibernate.Student" table="t_student">  

  7. <idnameidname="id">  

  8. <generatorclassgeneratorclass="native"/>  

  9. </id>  

  10. <propertynamepropertyname="name"/>  

  11. <many-to-onenamemany-to-onename="student" column="classId"cascade="save-update"/>  

  12. </class>  

  13. </hibernate-mapping>  

  14.    

 

单向一对多


同单向多一对的关系类似,单向一对多关系是同一个实体模型映射的不同关系模型。它是站在班级的角度去看问题的。也就是一的这一端去维护关系。也就是在加载一的时候,Hibernate会自动加载上多的一端数据。他的映射原理和单向一对多是一样的,都是在多的一端加入一个外键,指向一的一端。它的UML图如下,注意箭头的指向不同了。

 

对应的配置文件Student.hbm.xmlClasses.hbm.xml如下:

[html] view plain copy

  1. <?xmlversionxmlversion="1.0"?>  

  2. <!DOCTYPEhibernate-mapping PUBLIC  

  3. "-//Hibernate/HibernateMapping DTD 3.0//EN"  

  4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  

  5. <hibernate-mapping>  

  6. <class name="com.lsh.hibernate.Student" table="t_student">  

  7. <idnameidname="id">  

  8. <generatorclassgeneratorclass="native"/>  

  9. </id>  

  10. <propertynamepropertyname="name"/>  

  11. </class>  

  12. </hibernate-mapping>  

一的一端维护关系

[html] view plain copy

  1. <?xmlversionxmlversion="1.0"?>  

  2. <!DOCTYPEhibernate-mapping PUBLIC  

  3. "-//Hibernate/HibernateMapping DTD 3.0//EN"  

  4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  

  5. <hibernate-mapping>  

  6. <class name="com.lsh.hibernate.Classes" table="t_classes">  

  7. <idnameidname="id">  

  8. <generatorclassgeneratorclass="native"/>  

  9. </id>  

  10. <propertynamepropertyname="name"/>  

  11. <setnamesetname="students">  

  12. <!-- 

  13. <keycolumn="classesid" not-null="true"/> 

  14.  -->  

  15.  <key column="classesid"/>  

  16. <one-to-many class="com.lsh.hibernate.Student"/>  

  17. </set>  

  18. </class>  

  19. </hibernate-mapping>  

 

双向一对多


上面的两种关系都是单向的,但是在实际应用中,我们往往需要双向的加载。比如我拿到学生想知道他所在的班级,拿到班级想知道班里面有的学生。这样就需要双向的关系。还有一个很重要的原因就是,单向一对多关系在维护关系的过程中存在很大的缺陷。在插入学生的时候,如果班级不能为空,则学生是插入不了的。还有如果插入成功,在开始解决班级字段是空的,在事务提交阶段,班级需要更新每一个学生的班级ID,这样会产生大量的Update语句。影响效率。所以一对多关系大多使用双向一对多映射。

双向一对多映射的UML图是这样的。


它是一个双向的关联(这里仅限于对Hibernate使用,和现实关系有不一致的地方)

双向一对多的配置文件Student.hbm.xmlClasses.hbm.xml如下:

 

[html] view plain copy

  1. <?xmlversionxmlversion="1.0"?>  

  2. <!DOCTYPEhibernate-mapping PUBLIC  

  3. "-//Hibernate/HibernateMapping DTD 3.0//EN"  

  4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  

  5. <hibernate-mapping>  

  6. <classnameclassname="com.lsh.hibernate.Student" table="t_student">  

  7. <idnameidname="id">  

  8. <generatorclassgeneratorclass="native"/>  

  9. </id>  

  10. <propertynamepropertyname="name"/>  

  11. <many-to-onenamemany-to-onename="classes" column="classesid"/>  

  12. </class>  

  13. </hibernate-mapping>  

  14.    

 

[html] view plain copy

  1. <?xmlversionxmlversion="1.0"?>  

  2. <!DOCTYPEhibernate-mapping PUBLIC  

  3. "-//Hibernate/HibernateMapping DTD 3.0//EN"  

  4. "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  

  5. <hibernate-mapping>  

  6. <classnameclassname="com.lsh.hibernate.Classes" table="t_classes">  

  7. <idnameidname="id">  

  8. <generatorclassgeneratorclass="native"/>  

  9. </id>  

  10. <propertynamepropertyname="name"/>  

  11. <setnamesetname="students" inverse="true">  

  12.  <key column="classesid"/>  

  13. <one-to-manyclassone-to-manyclass="com.lsh.hibernate.Student"/>  

  14. </set>  

  15. </class>  

  16. </hibernate-mapping>  

它的映射原理是

  •  在一的一端的集合上采用<key>标签,在多的一端加入一个外键

  •   在多的一端采用<many-to-one>标签

也就是两端都要配置,和上面的两种有所不同。但是需要注意的是

  • <key>标签和<many-to-one>标签加入的字段保持一直,否则会产生数据混乱

  • 在一的一端加上inverse="true"属性,让一的一端不去维护关系,专业就不会发出更新语句。

 

下面解释一下配置文件中各个标签的意义和用法:

<many-to-one>

通过many-to-one元素,可以定义一种常见的与另一个持久化类的关联。这种关系模型是多对一关联(实际上是一个对象引用-译注):这个表的一个外键引用目标表的主键字段。

<one-to-many>

一对多关联,定义一个表的外键到另一个表的主键,另一个是多的一端。

<inverse>

inverse的值有两种,“true”和“false”。inverse="false"是默认的值,如果设置为true则表示对象的状态变化不会同步到数据库;设置成false则相反;

inverse的作用:在hibernate中是通过inverse的设置来决定是有谁来维护表和表之间的关系的。

 

 

需要说明的几点:

1:hibernate中的实体类和我们以前做的实体类不太一样,主要是以前的实体类如果包含其它表的字段,直接加上一个String或者int类型的数据就行。而Hibernate中需要加入的是一个实体类属性字段。但是两者生成的表是一样的。就像上面UML图体现的那样,第一个是Studnet实体类中有一个Classes类型的字段,第二个是Classes中有一个Student类型的集合。第三个是他们双方都有对方的一个引用。

2:一对多关系是比较常用的关系,很多时候都会映射出双向的一对多。

3:学习Hibernate要认真体会里面的实体关系,由此去推出映射关系。这里面用到了很多UML的知识。需要重点研究。

点击阅读全文查看"程序员的朋友圈都是怎样的,尤其是90后程序员,气哭"

有人用微信聊天,有人却在微信中学习,成长。下面是2016最HOT IT公众号,赶快试试新的关注方法吧!


关注方式
★长按二维码,选择“识别图中二维码”进行关注。

 没看够?更多好文在阅读原文

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值