
本着应用的目的快速学习Hibernate4框架
- Hibernate映射
前面的话
本节主要介绍:
- 一对多和多对一单向与双向映射
- 实际开发中需要注意的地方
学生和班级是典型的多对一,一对多关系,如图:
编写Student类
1 | package cn.codeforgod.model; |
编写Class类
1 | package cn.codeforgod.model; |
编写Student.hbm.xml
1 | <?xml version="1.0"?> |
说明:<many-to-one name="c" column="classId" class="cn.codeforgod.model.Class" cascade="save-update"></many-to-one>
这句代码说明Student对象中的字段c对应一个Class对象,多个Student对象对应一个Class对象,外键为classId。
cascade="save-update"是级联保存更新,这样当保存或更新一个Student对象时,如果Student对象中包含Class对象,那么自动保存更新Student内的Class对象。
如果此时不编写Class.hbm.xml中的一对多关系便是单向多对一映射。单向映射一般是指单向多对一映射。
编写Class.hbm.xml
1 | <?xml version="1.0"?> |
说明:
<set name="students" cascade="save-update" inverse="true">
<key column="classId"></key>
<one-to-many class="cn.codeforgod.model.Student"/>
</set>
以上代码说明Class对象中的students集合对应多个Student对象,一个Class对象对应多个Student对象,该字段在数据库中的名字是classId作为Student的外键。
cascade="save-update"是级联保存更新,这样当保存或更新一个Class对象时,如果Class对象中包含Student对象,那么自动保存更新Class内的Student对象。
inverse="true"表示该字段由”多”的一端来维护关系,这样的话cascade="save-update"便不起作用了。
Tip:*实际开发中大多也是在”多”端去维护”一”端的关系,因为业务等原因,你想啊,操作Student肯定比操作Class多,当同时在”多”端和”一”端维护关系时便会出现SQL冗余,Oh,What a pity!*
编写hibernate.cfg.xml
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--数据库连接设置 -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql:///db_hibernate</property>
<property name="connection.username">root</property>
<property name="connection.password">123456</property>
<!-- 方言 -->
<property name="dialect">org.hibernate.dialect.MySQL5Dialect</property>
<!-- 控制台显示SQL -->
<property name="show_sql">true</property>
<!-- 自动更新表结构 -->
<property name="hbm2ddl.auto">update</property>
<mapping resource="cn/codeforgod/model/Student.hbm.xml"/>
<mapping resource="cn/codeforgod/model/Class.hbm.xml"/>
<mapping resource="cn/codeforgod/model/Node.hbm.xml"/>
</session-factory>
</hibernate-configuration>
JUnit测试
1 | package cn.codeforgod.test; |
这里不再说明了,代码注释里写的很清楚了。
Tips:*关于关系映射要熟练掌握,仔细思考其中的原理才能运用得好~*
级联操作
级联操作是指操作设置级联方式的对象时,级联操作对应关系的其它对象,通过cascade属性配置,常用的值有:none,all,save-update,delete。
Tips:级联删除在开发过程中很少用,因为这样可能会导致业务数据丢失等问题。
关于级联操作更多请参考如下博文:
Hibernate关系映射
关于Hibernate关系映射我就不想多说了,一起来看看人家别人的见解:
以下内容摘自:Hibernate 实体关联关系映射—-总结
Hibernate映射关系错综复杂,在实际中真的都能用到吗?不用行吗?
在我看来,Hibernate提供这些映射关系,常用就是一对一和多对一,并且在能不用连接表的时候尽量不要用连接表。多对多会用到,如果用到了,应该首先考虑底层数据库设计是否合理。
在实际开发中,在Hibernate关联关系之外常常还有另外一种选择方案,表各自作为单表映射,业务逻辑控制外键关系(有时候就是一个相关联的列,但不一定要加外键约束),这样更加灵活,并且数据的完整性同样有保证。
当然,“单表映射,业务控制外键关系”并不是说Hibernate的实体关联功能是多余的,Hibernate的实体关联的优点很多,随便拿本书都是讲优点,用好了会让开发人员感觉更方便,现在我也是两种方案结合使用。比如对于不很确定的两个实体,常常选用单表关联。
以前在初学Hibernate还没有完全搞清楚这些关联关系的时候,就是用单表映射,业务控制外键关系做的,发现没有任何问题,程序同样运行得很好。
看了这些是不是后悔浪费时间学习映射关系了?呵呵,Hibernate的OR Mapping是Hibernate的灵魂,我相信Hibernate的创始人比我们一般人的理解更深刻。只有学会了这些才能体会Hibernate设计者的思想。学一个东西,不光自己写代码,还应该能看懂别人的代码才行。因此系统学习这些关联映射还是大有必要的。
然后关于深入理解关系映射我推荐一篇博文,写的真叫一个赞…赞…赞不绝口!
看完这篇博文,我感觉我有一种爱上这位博主的感觉了~(呵呵,开玩笑的啦^_^)
自身一对多、多对一介绍
应用举例:XML节点既可以是父节点也可以是子节点,一个父节点有多个子节点(一对多),多个子节点有共同的一个父节点(多对一),然后它们都是同一类型(都是节点),这就是典型的自身一对多、多对一的关系。
应用场景:在菜单(Menu)中,菜单项(MenuItem)既可以是父菜单也可以是子菜单,一个父菜单可以有多个子菜单,多个子菜单有同一个父菜单。
文字不如图片:

其实通过以上知识,完全可以编写此类应用,不过这个就当作检测自己的作业吧~(需要深刻理解一对多和多对一,要不连个放一起可能会晕+_+)
编写Node
1 | package cn.codeforgod.model; |
编写Node.hbm.xml
1 | <?xml version="1.0"?> |
我想,我还是把原理再讲一遍吧,我怕有人看不懂–!
<many-to-one name="parentNode" column="parentId" class="cn.codeforgod.model.Node" cascade="save-update"></many-to-one>
这句代码是说Node(自己)中的字段parentNode是Node类型,多个Node(自己)对应一个Node,外键是parentId。
<set name="childNodes" cascade="save-update" inverse="true">
<key column="parentId"></key>
<one-to-many class="cn.codeforgod.model.Node"/>
</set>
以上代码是说Node(自己)中的字段childNodes集合对应多个Node对象,一个Node(自己)对应多个Node,被参考的外键是parentId。
紧接着将<mapping resource="cn/codeforgod/model/Node.hbm.xml"/>写在Hibernate.cfg.xml中
JUnitTest
1 | package cn.codeforgod.test; |
末尾的话
本文采用hbm.xml方式配置映射规则,然而Hibernate官方推荐使用Annotation方式,然后据我了解,一流公司用Annotation,二流公司用xml,这两种方式优缺点参半,Annotation肯定要好一点的,个人建议先学xml(方式)再学Annotation(方式)。先会用,再深入。
Tips:
关于一对一和多对多的关系映射,请参考本站的Hibernate4Step2_2。