单表继承映射(一张表): 

 假设我们现在有三个类,关系如下:

  Person类有两个子类Student和Teacher,并且子类都具有自己独有的属性.这种实体关系在hibernate中可以使用单表的继承映射来建表,最后生成的表是这样的:

  可以看到我们只需要建立一张表就可以维护这个关系,这种方式就是单表继承映射,下面介绍配置方法:

  新建实体类Person ,Student,和Teacher :

public class Person {

    private int id;
private String name;
private int age;
//ge/set方法省略
}
/****************/
public class Student extends Person{ private String homework;
//ge/set方法省略
}
/****************/
public class Teacher extends Person{ private int salary;
//ge/set方法省略
}

  在当前包下新建Person类的映射文件Person.hbm.xml:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.wang.pojo">
<class name="Person" >
<id name="id">
<generator class="native"></generator>
</id>
<!-- 指明鉴别器 -->
<discriminator column="type" type="string"></discriminator>
<property name="name"></property>
<property name="age"></property>
<!-- 此标签是表明子类的列 name:子类的类名 discriminator-value="stu"是由hibernate维护Student的type的值 -->
<subclass name="Student" discriminator-value="stu">
<property name="homework"></property>
</subclass>
<subclass name="Teacher" discriminator-value="tea">
<property name="salary"></property>
</subclass>
</class>
</hibernate-mapping>

将Person.hbm.xml添加到hibernate.cfg.xml中. 新建一个测试类,测试1:自动生成数据库表 2:保存数据 3:读取数据(分别测试get方式 和 load方式 取数据,观察不同点):

@Test
public void testCreateDB() {
Configuration cfg = new Configuration().configure();
SchemaExport se = new SchemaExport(cfg);
// 第一个参数是否生成ddl脚本 第二个参数是否执行到数据库
se.create(true, true);
} @Test
public void testSave() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Teacher t1=new Teacher();
t1.setName("洪七公");
t1.setAge(65);
t1.setSalary(7000);
Student s1=new Student();
s1.setName("郭靖");
s1.setAge(26);
s1.setHomework("降龙十八掌");
Student s2=new Student();
s2.setName("黄蓉");
s2.setAge(23);
s2.setHomework("打狗棒法");
session.save(t1);
session.save(s1);
session.save(s2); tx.commit();
session.close();
} @Test
public void testGet() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Person p=(Person)session.get(Person.class, 2);
System.out.println("name:"+p.getName());
if(p instanceof Student){
Student s=(Student)p;
System.out.println("homework:"+s.getHomework());
}
tx.commit();
session.close();
}
@Test
public void testLoad() {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Person p=(Person)session.load(Person.class, 2);
System.out.println("name:"+p.getName());
if(p instanceof Student){
Student s=(Student)p;
System.out.println("homework:"+s.getHomework());
}
tx.commit();
session.close();
}

注意:

  在单表继承映射中,hibernate通过鉴别器 <discriminator>来识别不同的类,鉴别器由hibernate来维护.

  查询数据时,如果是使用session.get(...)方式获取到的类,可以进行多态的判断,如果是使用session.load(...)方式获取到的类,则不能进行多态的判断,在上面的testGet和testLoad中,打印出来的内容分别是:

name:郭靖

homeword:降龙十八掌

name:郭靖

可以看出,使用load方法,程序并没有进入通过if语句的判断.

每个子类对应一张表的继承映射(两张表):

  同样是上面的例子,我们也可以通过多张表来实现上述的继承关系,这种方式会分别生成Student表和Teacher表,结构是这样的:

teacher表:                                                                  Student表

                                

实体类是不需要改变的,只需要改变Person.hbm.xml即可:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.wang.pojo">
<!-- 指明Person表为抽象的,如果不加,会生成一张无用的Person表 -->
<class name="Person" abstract="true" >
<id name="id">
<!-- 设置主键生成策略为 指定主键,开发者需要手动设置主键id -->
<generator class="assigned"></generator>
</id>
<property name="name"></property>
<property name="age"></property>
<union-subclass name="Student">
<property name="homework"></property>
</union-subclass>
<union-subclass name="Teacher">
<property name="salary"></property>
</union-subclass>
</class>
</hibernate-mapping>

注意::

  在这种继承映射中,主键的生成方式不能设置为native,可以使用uuid,assigned,sequence等.

  这种表的生成方式更加合理,但是查询的效率不高.

每个类对应一张表的继承映射(3张表):

  上面的例子是使用两张表来实现继承映射的,其实还可以用三张表的方式,即Person,Student,Teacher各对应一张表,Person中保存公共属性的信息,Studnet,Teacher表中只保存自己独有的属性,表结构如下:

                                  

同样只需要修改Person.hbm.xml文件即可:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.wang.pojo"> <class name="Person" >
<id name="id">
<generator class="assigned"></generator>
</id>
<property name="name"></property>
<property name="age"></property>
<joined-subclass name="Teacher">
<key column="id"></key>
<property name="salary"></property>
</joined-subclass>
<joined-subclass name="Student">
<key column="id"></key>
<property name="homework"></property>
</joined-subclass>
</class>
</hibernate-mapping>

三种映射方式的比较:

  1.   第一种方式,只有一张表,数据冗余较多,但查询效率高,数据量不是非常大的时候,推荐使用.
  2.   第二种方式,每个子类对应一张表,数据冗余比较少,查询效率不高,主键不能设置成自增(native),需要指明为assigned,uuid,等.
  3.   第三种方式,每个类对应一张表,数据冗余较少,查询效率比第二种方式稍高,需要维护的表的个数较多.

hibernate笔记--继承映射关系的三种实现方式的更多相关文章

  1. Django-多对多关系的三种创建方式-forms组件使用-cookie与session-08

    目录 表模型类多对多关系的三种创建方式 django forms 组件 登录功能手写推理过程 整段代码可以放过来 forms 组件使用 forms 后端定义规则并校验结果 forms 前端渲染标签组件 ...

  2. Entity Framework 5.0系列之EF概览-三种编程方式

    概述 在开发面向数据的软件时我们常常为了解决业务问题实体.关系和逻辑构建模型而费尽心机,ORM的产生为我们提供了一种优雅的解决方案.ADO.NET Entity Framework是.NET开发中一种 ...

  3. (转)Hibernate关联映射——对象的三种关系

    http://blog.csdn.net/yerenyuan_pku/article/details/70148618 Hibernate关联映射——对象的三种关系 Hibernate框架基于ORM设 ...

  4. hibernate 继承映射关系( SINGLE_TABLE)

    三种继承映射关系.   1,SINGLE_TABLE   person student  teacher 在一个表中,student和teacher继承自person,通过一个Discriminato ...

  5. EF里的继承映射关系TPH、TPT和TPC的讲解以及一些具体的例子

    本章节讲解EF里的继承映射关系,分为TPH.TPT.TPC.具体: 1.TPH:Table Per Hierarchy 这是EF的默认的继承映射关系:一张表存放基类和子类的所有列,自动生成的discr ...

  6. entity framework里的继承映射关系TPH、TPT和TPC

    本章节讲解EF里的继承映射关系,分为TPH.TPT.TPC.具体: 1.TPH:Table Per Hierarchy 这是EF的默认的继承映射关系:一张表存放基类和子类的所有列,自动生成的discr ...

  7. EF——继承映射关系TPH、TPT和TPC的讲解以及一些具体的例子 05 (转)

    EF里的继承映射关系TPH.TPT和TPC的讲解以及一些具体的例子   本章节讲解EF里的继承映射关系,分为TPH.TPT.TPC.具体: 1.TPH:Table Per Hierarchy 这是EF ...

  8. python笔记-20 django进阶 (model与form、modelform对比,三种ajax方式的对比,随机验证码,kindeditor)

    一.model深入 1.model的功能 1.1 创建数据库表 1.2 操作数据库表 1.3 数据库的增删改查操作 2.创建数据库表的单表操作 2.1 定义表对象 class xxx(models.M ...

  9. hibernate的三种查询方式

    hibernate的三种查询方式 目录 hibernate的三种查询方式 1.HQL查询 1.1.SQL概述 1.2.实体查询 1.3.带where的查询 1.3.属性查询 1.4.实体的更新和删除 ...

随机推荐

  1. List、Map、Set三个接口,存取元素时,各有什么特点?

    List  以特定次序来持有元素,可有重复元素:Set  无法拥有重复元素,内部排序(无序):Map 保存key-value值,value可多值.

  2. WebService创建与使用

    因为项目中需要实现客户端与服务器端的数据交换,以及获取服务器端其他程序的分析结果,所以对WebService做了些简单的了解,现记录如下: 一.WebService程序编写 1.  在VS中新建空白网 ...

  3. 比achartengine更加强大的Android图表控件。

    比achartengine更加强大的图表控件MPAndroidChart. 详细使用及demo:http://www.see-source.com/androidwidget/detail.html? ...

  4. 为什么要重写hashcode() 方法

    Java中的集合(Collection)有两类,一类是List,再有一类是Set. 前者集合内的元素是有序的,元素可以重复:后者元素无序,但元素不可重复. 那么我们怎么判断两个元素是否重复呢? 这就是 ...

  5. 【三】用Markdown写blog的常用操作

    本系列有五篇:分别是 [一]Ubuntu14.04+Jekyll+Github Pages搭建静态博客:主要是安装方面 [二]jekyll 的使用 :主要是jekyll的配置 [三]Markdown+ ...

  6. android培训机构排名

    Android开发行业的热度打开了Android培训领域的市场,我们会发现有很多的Android培训机构都在大势宣传自己的师资.就业情况.教学环境等 ,然而到底要选择哪个呢?令很多的人困惑.2015年 ...

  7. [.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能

    [.net 面向对象程序设计进阶] (15) 缓存(Cache)(二) 利用缓存提升程序性能 本节导读: 上节说了缓存是以空间来换取时间的技术,介绍了客户端缓存和两种常用服务器缓布,本节主要介绍一种. ...

  8. RegSvr32注册OCX时报错

    RegSvr32注册OCX时报错. 错误1: 模块“dsoframer2007.ocx”已加载,但对 DllRegisterServer 的调用失败,错误代码为 0x80070005. 有关此问题的详 ...

  9. Linux查找命令:grep,awk,sed

    grep grep (global search regular expression(RE) and print out the line,全面搜索正则表达式并把行打印出来)是一种强大的文本搜索工具 ...

  10. hibernate用注解替代映射文件

    1.首先把原来的映射文件删掉,给实体类添加注解: @Entity //声明当前类为hibernate映射到数据库中的实体类 @Table(name="news") //声明tabl ...