一、综述

大家都知道,hibernate作为ORM框架的一个具体实现,最大的一个优点就是是我们的开发更加的能体现出“面向对象”的思想。在面向对象开发中,类与类之间是可以相互继承的(单向继承),而Hibernate中也对这种继承关系提供了自己风格的封装,这就是我们接下来要介绍的Hibernate继承映射的三种策略:

以下UML图类为例:

1、每棵类继承树一张表(可以理解为整棵树一张表,表内有所有字段)

2、每个类一张表(父类、子类、子类各一张表,父表中有公共字段,子表中有个性字段+外键约束)

3、每个具体类一张表(每个子类一张表,每张表都有自己所有的属性字段)

二、简介三种继承映射方式的实现:

实体类也就是我们的PO对象肯定是少不了的,这也是三种方式都必须要有的公共部分了算是:

Animal.Java:

  1. public class Animal {
  2. private int id;
  3. private String name;
  4. private String sex;
  5. public int getId(){
  6. return id;
  7. }
  8. public void setId(int id){
  9. this.id=id;
  10. }
  11. public String getName(){
  12. return name;
  13. }
  14. public void setSex(String name){
  15. this.name=name;
  16. }
  17. public String getSex(){
  18. return sex;
  19. }
  20. public void setSex(String sex){
  21. this.sex=sex;
  22. }
  23. }

Pig.java:

  1. public class Pig extends Animal{
  2. private int weight;
  3. public int getWeight(){
  4. return weight;
  5. }
  6. public void setWeight(){
  7. this.weight=weight;
  8. }
  9. }

Bird.java:

  1. public class Bird extends Animal{
  2. private int height;
  3. public int getHeight(){
  4. return height;
  5. }
  6. public void setHeight(){
  7. this.height=height;
  8. }
  9. }

三、配置文件分析:

1、每棵类继承树一张表(可以理解为整棵树一张表,表内有所有字段)

Extends.hbm.xml

  1. <hibernate-mapping package="com.ssh.hibernate">
  2. <class name="Animal">
  3. <id name="id">
  4. <generator class="native"/>
  5. </id>
  6. <discriminator column="type" type="string"></discriminator>
  7. <property name="name"/>
  8. <property name="sex"/>
  9. <subclass name="Pig" discriminator-value="Pig">
  10. <property name="weight"></property>
  11. </subclass>
  12. <subclass name="Bird" discriminator-value="Bird">
  13. <property name="height"></property>
  14. </subclass>
  15. </class>
  16. </hibernate-mapping>

配置映射文件时,父类还用<class>标签来定义;添加的区分字段(比如上面表1中的Type字段)需要用<discriminator>标签来定义;用<subclass>标签定义两个子类,与父类“合并”在同一张表里,子类的特有属性用<property>属性定义即可。

映射文件中的子类<subclass>标签还可以与标签同级,但是要加上属性extends,属性值为父类全路径名称。

  1. <hibernate-mapping package="com.ssh.hibernate">
  2. <class name="Animal">
  3. <id name="id">
  4. <generator class="native"/>
  5. </id>
  6. <discriminator column="type" type="string"></discriminator>
  7. <property name="name"/>
  8. <property name="sex"/>
  9. </class>
  10. <class name="Pig" discriminator-value="Pig" extends="com.ssh.vo.Animal">
  11. <property name="weight"></property>
  12. </class>
  13. <class name="Bird" discriminator-value="Bird" extends="com.ssh.vo.Animal">
  14. <property name="height"></property>
  15. </class>
  16. </hibernate-mapping>

这种映射方式可以把多个类放在一张表中,但是粒度比较粗,有冗余字段;但又是因为多个类的相关记录都存放在一张表中,查询时不用关联,因此效率较高。

2、每个类一张表(父类、子类、子类各一张表,父表中有公共字段,子表中有个性字段+外键约束)

Extends.hbm.xml

  1. <hibernate-mapping package="com.ssh.hibernate">
  2. <class name="Animal">
  3. <id name="id">
  4. <generator class="native"/>
  5. </id>
  6. <property name="name"/>
  7. <property name="sex"/>
  8. <joined-subclass name="Pig" table="t_pig">
  9. <key column="pid" />
  10. <property name="weight"/>
  11. </joined-subclass>
  12. <joined-subclass name="Bird" table="t_bird">
  13. <key column="bid"/>
  14. <property name="height"/>
  15. </joined-subclass>
  16. </class>
  17. </hibernate-mapping>

这种方案相对于上层实现(增删改查等操作)不变,因为对象模型并没有改变,只是关系模型改了,只需要修改映射文件即可。缺点:查询时需要关联表,效率差;插入时也要执行多个insert语句,适合继承程度不深的情况。优点:粒度较细,调理清楚,没有冗余。

3、每个具体类一张表(每个子类一张表,每张表都有自己所有的属性字段)

Extends.hbm.xml

  1. <hibernate-mapping package="com.ssh.hibernate">
  2. <class name="Animal" abstract="true">
  3. <id name="id">
  4. <generator class="uuid"/>
  5. </id>
  6. <property name="name"/>
  7. <property name="sex"/>
  8. <union-subclass name="Pig" table="t_pig">
  9. <property name="weight"/>
  10. </union-subclass>
  11. <union-subclass name="Bird" table="t_bird">
  12. <property name="height"/>
  13. </union-subclass>
  14. </class>
  15. </hibernate-mapping>

上面的表有个特点就是,t_pig和t_bird的主键永远都不会相同。因为表面上看起来这是两张表,但实际上存储的都是动物(同一类型),所以还可以看做是一张表。在配置文件中 <union-subclass>标签中不需要key值了,注意Animal的主键生成策略不能是自增(native)了,如果自增的话,pig表中第一条记录id为1,bird表中第一条记录也为1,而它们在实际意义上属于同一类型(可以看做在一张表中),否则可能造成不同子类对应表中的主键相同,所以主键不可一致。配置映射文件时,父类还用<class>标签来定义;用<union-subclass>标签定义两个子类,且每个类对应的表的信息是完全的,包含了所有从父类继承下来的属性。子类的特有属性同样用<property>定义即可。用abstract属性表示父类Animal为抽象类,这样Animal就不会映射成表了。

四、总结:

如果系统需要经常进行查操作且子类数量较多,则建议用第一种方案,即每棵生成树映射一张表,这也是最常用的方法,效率较高。如果追求细粒度的设计且子类数量不多,则可以用后两种方案:每个类映射一张表或每个具体类映射一张表。

假如说我们就是有三张表,分别是T_Animal、T_Pig、T_Bird就是要求我们用sql语句来完成这些级联,大家想过sql语句与hbm.xml配置文件的映射关系吗?其实他就是帮我们做的表union和表join整合思想,大家可以思考一下这个问题。

【Hibernate框架】三种继承映射的更多相关文章

  1. Hibernate的三种状态及对象生命周期

        理解Hibernate的三种状态,更利于理解Hibernate的运行机制,这些可以让你在开发中对疑点问题的定位产生关键性的帮助. 三种状态 临时状态(Transient):在通过new关键字, ...

  2. js的三种继承方式及其优缺点

    [转] 第一种,prototype的方式: //父类 function person(){ this.hair = 'black'; this.eye = 'black'; this.skin = ' ...

  3. C++的三种继承方式简述

    C++对父类(也称基类)的继承有三种方式,分别为:public继承.protected继承.private继承.三种继承方式的不同在于继承之后子类的成员函数的"可继承性质". 在说 ...

  4. hibernate的三种状态(儿)

    第五讲:hibernate的三种状态 瞬时:bean对象与session,与数据库无关.在session对象的save方法保存之前. 持久状态(托管):bean对象与session有关,数据库中有对应 ...

  5. 第五讲:深入hibernate的三种状态

    学过hibernate的人都可能都知道hibernate有三种状态,transient(瞬时状态),persistent(持久化状态)以及detached(离线状态),大家伙也许也知道这三者之间的区别 ...

  6. [转]深入hibernate的三种状态

    学过hibernate的人都可能都知道hibernate有三种状态,transient(瞬时状态),persistent(持久化状态)以及detached(离线状态),大家伙也许也知道这三者之间的区别 ...

  7. 深入hibernate的三种状态

    学过hibernate的人都可能都知道hibernate有三种状态,transient(瞬时状态),persistent(持久化状态)以及detached(离线状态),大家伙也许也知道这三者之间的区别 ...

  8. C++继承(一) 三种继承方式

    继承定义 继承是使代码可以复用的重要手段,也是面向对象程序设计的核心思想之一. 继承就是不修改原有的类,直接利用原来的类的属性和方法并进行扩展.原来的类称为基类,继承的类称为派生类,他们的关系就像父子 ...

  9. c++三种继承方式public,protect,private

    C++中的三种继承public,protected,private 三种访问权限 public:可以被任意实体访问 protected:只允许子类及本类的成员函数访问 private:只允许本类的成员 ...

随机推荐

  1. Node.js之路【第二篇】Nodejs中的pip(NPM)&REPL

    什么是NPM 在学Python的时候我们肯定会使用第三方模块或者编写模块供别人使用,我们有一个非常好用的pip来帮我们管理我们的模块包!那么Nodejs重的模块包呢? 对没错就是NPM,他是随同Nod ...

  2. 记录分享公司Spring data相关配置

    起因 公司Spring Data相关的配置还是有点意思的,不过蛮复杂的...XML很多...我不太喜欢强行记住....所以我打算记录一下配置的大致思路和结构,以后可能会有用.... 总体结构 总体结构 ...

  3. C#编写window服务,一步一步(1)

    Window服务是啥,这里就不废话了,如何用在哪里用也不废话了,这里我这篇文章只是详述了我在vs2012中创建window服务的经过,希望对你有所帮助. 另外:我在编写服务过程中参考了 Profess ...

  4. Linux C++中的时间函数(转)

    http://net.pku.edu.cn/~yhf/linux_c/function/03.html   asctime(将时间和日期以字符串格式表示) 相关函数 time,ctime,gmtime ...

  5. logback日志写入数据库(mysql)配置

    如题  建议将日志级别设置为ERROR.这样可以避免存储过多的数据到数据中. 1  logback 配置文件(如下) <?xml version="1.0" encoding ...

  6. C# Byte[] 转String 无损转换

    C# Byte[] 转String 无损转换 转载请注明出处 http://www.cnblogs.com/Huerye/ /// <summary> /// string 转成byte[ ...

  7. Eclipse 导入外部项目无法识别为web项目并且无法在部署到tomcat下

    uss_web如果没有左上角那个球,tomcat就识别不出来的. 1.进入项目目录,找到.project文件,打开. 2.找到...代码段,加入如下标签内容并保存: <nature>org ...

  8. easyui textbox 添加 onblur 失去焦点事件

    由于textbox不能触发onblur事件,需要换种方式解决问题,方案如下: <input type="text" class="easyui-textbox&qu ...

  9. Bootstrap table使用心得

    序号显示带分页信息的连续编号,在序号列添加以下格式化代码即可. { field: 'number', title: '序号', align:'center', width:45, formatter: ...

  10. JavaScript学习笔记(1))——————call,apply方法

    学习前端也有一段时间了,但是效果甚微.利用时间不够充分,虽然是利用工作之余来学习.但是这不能成为我的借口. 今天学习了(其实看了很多遍)call apply方法. function abc(a,b){ ...