对于面向对象的程序设计语言,继承、多态是两个最基本的概念。Hibernate的继承映射可以理解两个持久化类之间的继承关系。

Hibernate支持几种继承映射策略,不管哪种继承映射策略,Hibernate的多态查询都可以很好的运行。

假设有四个对象:Department、Employee、Skiller、Sales。他们四个对象存在如下关系:

从上面的关系可知:Employee与Department之间存在N-1的关联关系。Skiller和Sales都是Employee的子类。下面是这四个类的代码:

Department

public class Department {private Integer id;private String name;private Set<Employee> employees;          //关联关系//省略setter和getter方法
}

Employee

public class Employee {private Integer id;private String name;private Department department;//省略setter和getter方法
}

Skiller

public class Skiller extends Employee {private String skiller;//省略setter和getter方法
}

Sales

public class Sales extends Employee {private int sell;//省略setter和getter方法
}

一、采用subclass元素的继承映射

在这种继承映射策略下,整个继承树的所有实例都将保存在同一张表中。因为是将父类、子类的实例全部保存在同一张表中,所以需要在该表中添加列,通过该列可以区分每行记录到底是属于哪个类的实例---这个列被称之为辨别者。

在这种继承映射策略下,我们需要使用<subclass.../>元素来映射子类的持久化类,使用<discrimainator.../>元素来映射辨别者,同时还需要给<subclass.../>元素增加discriminator-value属性来指定每个类的辨别者的值。

映射文件如下:

<hibernate-mapping package="com.hibernate.domain"><class name="Employee" table="employee"><id name="id" column="employeeID"><generator class="hilo" /></id><!-- 映射辨别者 --><discriminator column="type" type="string" /><property name="name" column="employeeName" /><!-- 用于映射N-1关联实体,指定关联实体类为 :Department,指定外键为:departmentID--><many-to-one name="department" column="departmentID" />  <!-- 使用subclass元素映射Employee的子类Skiller --> <subclass name="Skiller" discriminator-value="skiller"><property name="skiller" /></subclass><!-- 使用subclass元素映射Employee的子类Sales --> <subclass name="Sales" discriminator-value="sales"><property name="sell" /></subclass></class>
</hibernate-mapping>

在这里我们只需要给父类进行映射就可以了。在这个配置文件中,指定了一个辨别者列:type,该列其本省是没有任何意义的,只是起到一个区分每条记录时对应哪个持久化类的作用。其中Skiller类的辨别者列type的值为skiller,Sales类的辨别者列type的值为sales。通过下面的程序段来进行操作。

 static void add(){Session session = HibernateUtil.getSession();Transaction tx = session.beginTransaction();Department department = new Department();department.setName("department name1");Employee emp1 = new Employee();emp1.setName("employy name1");emp1.setId(1);Skiller emp2 = new Skiller();emp2.setSkiller("电工");emp2.setName("employee name2");emp2.setDepartment(department);        //建立对象之间的关联关系Sales emp3= new Sales();emp3.setSell(50);emp3.setName("employee name3");emp3.setDepartment(department);        //建立对象之间的关联关系session.save(department);session.save(emp1);session.save(emp2);session.save(emp3);tx.commit();session.close();}

上面的程序段,hibernate将会产生如下的几条SQL语句:

Hibernate: insert into department (departmentName) values (?)Hibernate: insert into employee (employeeName, departmentID, type) values (?, ?, 'com.hibernate.domain.Employee')Hibernate: insert into employee (employeeName, departmentID, skiller, type) values (?, ?, ?, 'skiller')Hibernate: insert into employee (employeeName, departmentID, sell, type) values (?, ?, ?, 'sales')

在第二条sql语句,type的值为com.hibernate.domain.Employee。对于这个值可以理解为空。在第三条sql语句中,type的值为skiller,第四天sql语句中type值为sales。同时要注意第三条sql语句中的sell列是没有值的,第四条的skiller列同样也没有值。所以在这里一定要注意:使用subclass继承映射策略时,其子类中增加的属性映射的字段是一定不能有非空约束的。

表结构如下:

通过下面的程序段,来进行查询操作:

 static void query(int empid){Session session = HibernateUtil.getSession();Employee emp = (Employee) session.get(Employee.class, empid);}

得到如下SQL语句:

Hibernate: select employee0_.employeeID as employeeID2_0_, employee0_.employeeName as employee3_2_0_, employee0_.departmentID as departme4_2_0_, employee0_.skiller as skiller2_0_, employee0_.sell as sell2_0_, employee0_.type as type2_0_ from employee employee0_ where employee0_.employeeID=?

从上面的sql语句可以看到它是从一张表中获取所有的记录。这正是这种继承策略的一个非常大的好处:在这种映射策略下,整棵继承树的所有数据都保存在一张表中,因此不管进行怎样的查询,不管查询继承树中的那一层的实体,底层数据库都只需要在一张表中查询即可,非常方便、高效。

我们在这里给上面的查询代码增加一句:System.out.println(emp.getClass());

依次给empid赋值为:1、2得到的结果如下:

1、class com.hibernate.domain.Employee

2、class com.hibernate.domain.Skiller

有上面的输出结果可知:hibernate能够非常好处理多态查询。

一、采用joined-subclass元素的继承映射

采用这种策略时,父类实例保存在父类表里,而子类实例则有父类表和子类表共同存储。在这种策略下,是将父类与子类共有的属性保存在父类表中,而子类特有的属性,则保存在子类表中,就是说,父类一张表,子类一张表,同时子类表中需要增加父类表的外键。

采用joined-subclass来映射这种策略,并且需要为每个子类使用<key.../>元素映射共有主键--这个主键类还将参照父表的主键列。

映射文件如下:

<hibernate-mapping package="com.hibernate.domain"><class name="Employee" table="employee"><id name="id" column="employeeID"><generator class="hilo" /></id><property name="name" column="employeeName" /><!-- 用于映射N-1关联实体,指定关联实体类为 :Department,指定外键为:departmentID--><many-to-one name="department" column="departmentID" />  <!-- 使用join-class元素映射Employee类的Skill而子类 --><joined-subclass name="Skiller"><!-- 必须使用key元素映射父子类的共有主键 --><key column="employee_id" /><property name="skiller" /></joined-subclass><!-- 使用join-class元素映射Employee类的Sales而子类 --><joined-subclass name="Sales"><!-- 必须使用key元素映射父子类的共有主键 --><key column="employee_id" /><property name="sell" /></joined-subclass></class>
</hibernate-mapping>

通过上面的增加代码,执行添加操作。得到如下结果:

     

SQL语句如下:

Hibernate: insert into department (departmentName) values (?)Hibernate: insert into employee (employeeName, departmentID) values (?, ?)Hibernate: insert into employee (employeeName, departmentID) values (?, ?)Hibernate: insert into Skiller (skiller, employee_id) values (?, ?)Hibernate: insert into employee (employeeName, departmentID) values (?, ?)Hibernate: insert into Sales (sell, employee_id) values (?, ?)

从上面的SQL语句中也可以看出hibernate对与这种继承映射策略的处理。父类一张表,子类一张表同时子类引用父类外键建立关联关系。

对与这样继承映射策略的查询,hibernate采用表连接方式来获取子类表的信息:

Hibernate: select employee0_.employeeID as employeeID2_0_, employee0_.employeeName as employee2_2_0_, employee0_.departmentID as departme3_2_0_, employee0_1_.skiller as skiller3_0_, employee0_2_.sell as sell4_0_, case when employee0_1_.employee_id is not null then 1 when employee0_2_.employee_id is not null then 2 when employee0_.employeeID is not null then 0 end as clazz_0_ from employee employee0_ left outer join Skiller employee0_1_ on employee0_.employeeID=employee0_1_.employee_id left outer join Sales employee0_2_ on employee0_.employeeID=employee0_2_.employee_id where employee0_.employeeID=?

所以当使用joined-subclass继承映射策略,当程序查询子类实例时,需要跨越多个字表查询,其复杂度取决于该子类有多少层父类。这样势必会对查询的性能有些影响。

一、采用union-subclass元素的继承映射

采用这样继承映射策略,父类实例的数据保存在父表中,子类实例的数据仅仅只保存在字表中,没有在附表中有任何记录。在这种继承映射策略下,子表的字段会比父表的字段多。

同时在这种映射策略,既不需要使用辨别者,也不需要使用<key.../>元素来映射共有主键。

映射文件如下:

<hibernate-mapping package="com.hibernate.domain"><class name="Employee" table="employee"><id name="id" column="employeeID"><generator class="hilo" /></id><property name="name" column="employeeName" /><!-- 用于映射N-1关联实体,指定关联实体类为 :Department,指定外键为:departmentID--><many-to-one name="department" column="departmentID" />  <!-- 使用union-subclass元素映射Employee类的子类:Skiller --><union-subclass name="Skiller" table="skiller"><property name="skiller" /></union-subclass><!-- 使用union-subclass元素映射Employee类的子类:Sales --><union-subclass name="Sales" table="sales"><property name="sell" /></union-subclass></class>
</hibernate-mapping>

注:在这种映射策略下,映射持久化类是不能使用identity主键生成策略。

通过添加操作得到如下的两个子类表:

采用这中映射策略,底层数据库的数据看起来更加符合正常情况下的数据库设计,不同实体保存在不同的数据表中。

转载于:https://www.cnblogs.com/oversea201405/archive/2012/07/06/3752337.html

Hibernate读书笔记---继承映射相关推荐

  1. Hibernate学习(3) (继承映射,配置文件和注解版)

    这篇blog准备写怎样在Hibernate中反应内存对象之间的继承关系.我们知道,内存对象之间是可以有继承关系的,但是在数据库中,我们继承神马的都是浮云,不存在的.那么怎么办呢?Hibernate提供 ...

  2. (8)hibernate四种继承映射

    一 一个类继承体系一张表 1 对象模型(java类结构) 2 映射后据库中的表 3 代码 Employee.java package com.learning;public class Employe ...

  3. Hibernate读书笔记

    伟大的信息管理与信息系统专业,万恶的信息管理与信息系统专业.说这句话我是有根据的:因为这个专业雄心勃勃的想把自己的子弟培养成全面发展的人才但是结果则不然.两方面的原因:一部分在学生,但是一部分在这个专 ...

  4. java核心技术读书笔记—继承

    继承 1 类.超类及子类 1.1 定义子类 在java中,使用关键字extends进行继承,具体实现方式如下,这里Manager表示子类,Employee表示超类,下面所示关系是类Manager继承于 ...

  5. Hibernate之继承映射

    Hibernate的继承映射可以理解为两个持久化类之间的继承关系    例如老师和人之间的关系 持久化类  Person类 public  class  Person { private   Inte ...

  6. 《C#图解教程》读书笔记之四:类和继承

    本篇已收录至<C#图解教程>读书笔记目录贴,点击访问该目录可获取更多内容. 一.万物之宗:Object (1)除了特殊的Object类,其他所有类都是派生类,即使他们没有显示基类定义. ( ...

  7. C#读书笔记之继承、接口与抽象类续

    C#读书笔记之继承.接口与抽象类 http://www.cnblogs.com/linjzong/articles/2717173.html 接下来说明最开始提出的问题:为什么要使用接口和抽象类? 刚 ...

  8. 浅析Hibernate映射(三)——继承映射

    对象模型示例: 继承映射的实现方式有三种: (一)每棵类继承树一张表 关系模型: 映射文件: <hibernate-mapping package="com.jialin.hibern ...

  9. Hibernate继承映射

    Hibernate继承映射 在面向对象的程序领域中,类与类之间是有继承关系的,例如Java世界中只需要extends关键字就可以确定这两个类的父子关系,但是在关系数据库的世界中,表与表之间没有任何关键 ...

最新文章

  1. cisco 核心交换机连接两个路由器_CISCO、H3C、华为三层交换机端口二三层切换命令对比...
  2. 使用dotnet-dump 查找 .net core 3.0 占用CPU 100%的原因
  3. 参与有奖 | Arthas 第 5 期征文活动火热开启!(内附第四期中奖名单)
  4. python发送邮件及附件
  5. Object类的toString方法
  6. 基于ASP.NET Core api 的服务器事件发送
  7. 新加坡推出人工智能计划AI.SG 迎战人工智能和数据科学关键难题
  8. 【前端基础】querySelector
  9. python第一行左对齐_关于Python的第一行语句
  10. 单片机蜂鸣器源代码+仿真
  11. 开源硬件的知识产权管理
  12. 计算机存储器分级结构,存储器
  13. 使用Rancher的RKE部署Kubernetes要点
  14. 数据如何变成知识(2):数据湖和数据沼泽
  15. java计算机毕业设计高校四六级报名管理系统源程序+mysql+系统+lw文档+远程调试
  16. 航拍无人机 无人车_无人机将有自己的时刻
  17. 计算机软件从业证书,互联网行业从业人员证书
  18. 【ML】Naive Bayes
  19. matlab变量相加,如何在空间计量matlab程序中加入更多的变量?
  20. 累了,困了,来看“MySQL”,让你梦回吹角连营

热门文章

  1. 穷人怎么慢慢打破阶层?做到这2点,活出最真实的样子,别表演!
  2. 失业了又不想进厂打工,怎么办
  3. 结合我的创业经历,有一下3点感受
  4. 哪个行业既锻炼人又便于今后创业?
  5. OpenStack 的诞生
  6. 让游戏达到60帧真的重要吗?
  7. 【Java开发规范】禁止在 foreach 循环里进行元素的 remove/add 操作
  8. uni-app中view组件的基本使用
  9. azure 入门_Azure Databricks入门指南
  10. ssas表格模型 权限控制_性能调整SSAS表格模型