`

Hibernate读书笔记---继承映射

阅读更多

 

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

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

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

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

Department

Java代码 
  1. public class Department {  
  2.     private Integer id;  
  3.     private String name;  
  4.     private Set<Employee> employees;          //关联关系  
  5.       
  6.     //省略setter和getter方法  
  7. }  

Employee

Java代码 
  1. public class Employee {  
  2.     private Integer id;  
  3.     private String name;  
  4.     private Department department;  
  5.     //省略setter和getter方法  
  6. }  

Skiller

Java代码 
  1. public class Skiller extends Employee {  
  2.     private String skiller;  
  3.     //省略setter和getter方法  
  4. }  

Sales

Java代码 
  1. public class Sales extends Employee {  
  2.     private int sell;  
  3.     //省略setter和getter方法  
  4. }  

 

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

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

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

映射文件如下:

 

Html代码 
  1. <hibernate-mapping package="com.hibernate.domain">  
  2.     <class name="Employee" table="employee">  
  3.         <id name="id" column="employeeID">  
  4.             <generator class="hilo" />  
  5.         </id>  
  6.          <!-- 映射辨别者 -->  
  7.         <discriminator column="type" type="string" />  
  8.           
  9.         <property name="name" column="employeeName" />  
  10.         <!-- 用于映射N-1关联实体,指定关联实体类为 :Department,指定外键为:departmentID-->  
  11.         <many-to-one name="department" column="departmentID" />    
  12.           
  13.         <!-- 使用subclass元素映射Employee的子类Skiller -->   
  14.         <subclass name="Skiller" discriminator-value="skiller">  
  15.             <property name="skiller" />  
  16.         </subclass>  
  17.           
  18.         <!-- 使用subclass元素映射Employee的子类Sales -->   
  19.         <subclass name="Sales" discriminator-value="sales">  
  20.             <property name="sell" />  
  21.         </subclass>  
  22.     </class>  
  23. </hibernate-mapping>  

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

 

Html代码 
  1. static void add(){  
  2.     Session session = HibernateUtil.getSession();  
  3.     Transaction tx = session.beginTransaction();  
  4.       
  5.     Department department = new Department();  
  6.     department.setName("department name1");  
  7.       
  8.     Employee emp1 = new Employee();  
  9.     emp1.setName("employy name1");  
  10.     emp1.setId(1);  
  11.       
  12.     Skiller emp2 = new Skiller();  
  13.     emp2.setSkiller("电工");  
  14.     emp2.setName("employee name2");  
  15.     emp2.setDepartment(department);        //建立对象之间的关联关系  
  16.       
  17.     Sales emp3new Sales();  
  18.     emp3.setSell(50);  
  19.     emp3.setName("employee name3");  
  20.     emp3.setDepartment(department);        //建立对象之间的关联关系  
  21.       
  22.     session.save(department);  
  23.     session.save(emp1);  
  24.     session.save(emp2);  
  25.     session.save(emp3);  
  26.       
  27.     tx.commit();  
  28.     session.close();  
  29.       
  30. }  

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

 

Sql代码 
  1. Hibernate: insert into department (departmentName) values (?)  
  2.   
  3. Hibernate: insert into employee (employeeName, departmentID, type) values (?, ?, 'com.hibernate.domain.Employee')  
  4.   
  5. Hibernate: insert into employee (employeeName, departmentID, skiller, type) values (?, ?, ?, 'skiller')  
  6.   
  7. 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继承映射策略时,其子类中增加的属性映射的字段是一定不能有非空约束的。

表结构如下:

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

Java代码 
  1. static void query(int empid){  
  2.  Session session = HibernateUtil.getSession();  
  3.  Employee emp = (Employee) session.get(Employee.class, empid);  
  4. }  

得到如下SQL语句:

Sql代码 
  1. 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_   
  2.   
  3. from employee employee0_ where employee0_.employeeID=?  


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

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

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

1、classcom.hibernate.domain.Employee

2、classcom.hibernate.domain.Skiller

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

 

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

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

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

映射文件如下:

 

Html代码 
  1. <hibernate-mapping package="com.hibernate.domain">  
  2.     <class name="Employee" table="employee">  
  3.         <id name="id" column="employeeID">  
  4.             <generator class="hilo" />  
  5.         </id>  
  6.   
  7.         <property name="name" column="employeeName" />  
  8.         <!-- 用于映射N-1关联实体,指定关联实体类为 :Department,指定外键为:departmentID-->  
  9.         <many-to-one name="department" column="departmentID" />    
  10.   
  11.         <!-- 使用join-class元素映射Employee类的Skill而子类 -->  
  12.         <joined-subclass name="Skiller">  
  13.             <!-- 必须使用key元素映射父子类的共有主键 -->  
  14.             <key column="employee_id" />  
  15.             <property name="skiller" />  
  16.         </joined-subclass>  
  17.           
  18.         <!-- 使用join-class元素映射Employee类的Sales而子类 -->  
  19.         <joined-subclass name="Sales">  
  20.             <!-- 必须使用key元素映射父子类的共有主键 -->  
  21.             <key column="employee_id" />  
  22.             <property name="sell" />  
  23.         </joined-subclass>  
  24.     </class>  
  25. </hibernate-mapping>  


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

SQL语句如下:

 

Sql代码 
  1. Hibernate: insert into department (departmentName) values (?)  
  2.   
  3. Hibernate: insert into employee (employeeName, departmentID) values (?, ?)  
  4.   
  5. Hibernate: insert into employee (employeeName, departmentID) values (?, ?)  
  6.   
  7. Hibernate: insert into Skiller (skiller, employee_id) values (?, ?)  
  8.   
  9. Hibernate: insert into employee (employeeName, departmentID) values (?, ?)  
  10.   
  11. Hibernate: insert into Sales (sell, employee_id) values (?, ?)  


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

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

 

Sql代码 
  1. 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   
  2.   
  3. when employee0_1_.employee_id is not null then 1   
  4.   
  5. when employee0_2_.employee_id is not null then 2   
  6.   
  7. when employee0_.employeeID is not null then 0 end as clazz_0_   
  8.   
  9. from employee employee0_ left   
  10.   
  11. outer join Skiller employee0_1_   
  12.   
  13. on employee0_.employeeID=employee0_1_.employee_id   
  14.   
  15. left outer join Sales employee0_2_   
  16.   
  17. on employee0_.employeeID=employee0_2_.employee_id   
  18.   
  19. where employee0_.employeeID=?  


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

 

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

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

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

映射文件如下:

 

Html代码 
  1. <hibernate-mapping package="com.hibernate.domain">  
  2.     <class name="Employee" table="employee">  
  3.         <id name="id" column="employeeID">  
  4.             <generator class="hilo" />  
  5.         </id>  
  6.   
  7.         <property name="name" column="employeeName" />  
  8.         <!-- 用于映射N-1关联实体,指定关联实体类为 :Department,指定外键为:departmentID-->  
  9.         <many-to-one name="department" column="departmentID" />    
  10.   
  11.         <!-- 使用union-subclass元素映射Employee类的子类:Skiller -->  
  12.         <union-subclass name="Skiller" table="skiller">  
  13.             <property name="skiller" />  
  14.         </union-subclass>  
  15.           
  16.         <!-- 使用union-subclass元素映射Employee类的子类:Sales -->  
  17.         <union-subclass name="Sales" table="sales">  
  18.             <property name="sell" />  
  19.         </union-subclass>  
  20.     </class>  
  21. </hibernate-mapping>  


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

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

 

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

 

 

 

3
8
分享到:
评论

相关推荐

    Hibernate学习笔记(1-13)

    5. **继承映射**: - 支持类继承关系的映射,可以将子类对象的数据存储在同一个表或者不同的表中。 6. **集合映射**: - 如List、Set、Map等集合对象与数据库表之间的映射处理。 7. **懒加载**: - 一种优化...

    Hibernate实战笔记

    ### Hibernate实战笔记——深入解析对象关系映射与优化策略 #### 一、对象关系映射(ORM)概念 - **什么是持久化**:在计算机科学领域,“持久化”指的是将程序的数据状态保存到非易失性的存储介质中,以便可以在...

    hibernate-note学习笔记

    ### hibernate-note学习笔记知识点详解 #### 一、对象持久化 **1.1 概述** 对象持久化是指将程序中的对象状态保存到非易失性存储中(如硬盘或磁盘等),以便在系统重启后仍能保留这些状态。这种技术常用于将对象的...

    Hibernate学习笔记

    #### 继承映射 Hibernate支持多种继承策略,包括单表策略、每个子类一张表策略以及混合策略。 1. **单表策略**: - 所有子类共享同一张表。 - 使用`&lt;subclass&gt;`标签来定义子类。 2. **每个子类一张表策略**: ...

    hibernate学习笔记

    - **多表继承映射关系**:`多表继承映射关系.PNG` 可能涵盖了Hibernate的联合继承和表-per-hierarchy策略,其中每个子类对应单独的表或共享一部分字段。 **4. 映射类型** `其他映射(set,list,string,map)-3.PNG` ...

    淘宝实习笔记--webx学习之旅

    【淘宝实习笔记--webx学习之旅】这篇笔记主要记录了作者在淘宝实习期间关于Webx框架的学习和理解。Webx是一个用于构建企业级Web应用程序的框架,它在淘宝内部广泛使用。以下是一些核心知识点: 1. **iBATIS**:...

    SSH笔记-Mapping

    本笔记主要探讨SSH中的映射关系,包括基于外键/主键的一对一映射、多对多映射以及映射继承。 1. **基于外键/主键一对一映射** 在数据库设计中,一对一关系通常通过外键实现。在SSH框架中,我们可以通过Hibernate的...

    hibernate框架开发2016版视频 四天学习笔记完整版

    2016年版本的Hibernate在继承了其早期版本的优秀特性基础上,又进行了一些改进和优化,使得其更加适合现代应用程序的需求。 首先,我们需要理解Hibernate的核心概念——对象关系映射(ORM)。ORM是将数据库中的表...

    Hibernate学习笔记_songjignhao_1

    总的来说,这篇 Hibernate 学习笔记涵盖了关联关系的多种类型和映射方法,以及查询排序、组件映射和继承映射等核心概念,为理解并熟练运用 Hibernate 提供了坚实的基础。通过实际编码和理解这些示例,开发者可以更...

    2023年Java相关课程系列笔记之十四Hibernate学习笔记.doc

    - 支持对象的关联和继承映射,使得数据模型更接近面向对象设计。 1.3 JDBC访问数据库的缺陷 - 手动编写的SQL语句易出错且不易维护。 - 缺乏统一的API,不同的数据库系统需要编写不同的SQL。 - 缓存管理、事务处理等...

    Hibernate 的学习笔记

    #### 九、继承映射 - **类型**: - 单表继承:多个子类共享一张表。 - 每个子类一张表:每个子类都有单独的表。 - 分级表继承:使用一个主表和多个扩展表。 #### 十、集合映射 - **类型**: - `Set`:无序不...

    hibernate4框架学习笔记

    【hibernate4框架学习笔记】 Hibernate是一款强大的ORM(Object-Relational Mapping)框架,它在Java开发中扮演着至关重要的角色,通过提供对象与数据库之间的映射,解决了对象模型和关系模型之间的“阻抗不匹配”...

    java学习笔记-html-ssh-js

    - **Hibernate**:持久化框架,简化数据库操作,实现对象-关系映射。 - **Struts**:MVC框架,处理用户请求并转发到相应的业务逻辑。 以上只是Java学习笔记的部分概览,具体的学习过程还需深入每个知识点,通过...

    hibernate 学习笔记4

    多态映射(也称为继承映射)是 Hibernate 中用于处理类继承的一种机制。它允许你在不同的层次结构中管理对象,同时保持数据的完整性和一致性。Hibernate 支持三种不同的多态映射策略:每个类一张表、每个具体类一张...

    强人Hibernate文档笔记

    【强人Hibernate文档笔记】是针对Hibernate框架的深入学习资料,涵盖了对象定义、实例状态、JMX集成和JCA支持等关键概念。以下是对这些内容的详细解释: **一、对象定义** 1. **SessionFactory**: SessionFactory是...

    Hibernate笔记

    ### Hibernate 数据持久化组件 #### 一、概述与基本概念 **Hibernate** 是一款非常流行的 Java 持久层框架,它提供了...正确理解和使用 Hibernate 的配置文件和映射文件对于成功地集成 Hibernate 至项目中至关重要。

Global site tag (gtag.js) - Google Analytics