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

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

  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. java web(六)多个请求对应一个Servlet

    概要: 提交请求的常用方式有两种,get/post , 运行程序后被请求,在加载执行web.xml文件时通过该文件中的映射关系找到即将要执行的Servlet; 而在要执行的Servlet文件中可通过反 ...

  2. sqlserver2008附加数据库时提示“无法为该请求检索数据。 (Microsoft.SqlServer.Management.Sdk.Sfc)”

    解决方案: 右击SQL Server Management Studio以管理员身份运行,选择与脱机数据库时相同的登陆方式(win还是sa),进入后再附加就是ok了.

  3. c#动态编译并动态生成dll

    /// <summary> /// 动态编译并执行代码 /// </summary> /// <param name="code">代码< ...

  4. DevExpress控件的GridControl控件小结

    DevExpress控件的GridControl控件小结 (由于开始使用DevExpress控件了,所以要点滴的记录一下) 1.DevExpress控件组中的GridControl控件不能使横向滚动条 ...

  5. Android课程---关于数据存储的学习(3)之数据库和事务

    DataActivity3.java package com.hanqi.test5; import android.content.ContentValues; import android.dat ...

  6. 实验环境里新创建成功的web application却在浏览器中返回404错误

    刚刚翻笔记翻到一些刚学SharePoint时候解决的一些很2的初级问题,本来是有些挣扎该不该把它们记录到这个blog里的?因为担心这些很初级的文章会拉低这个blog的逼格,但是我的哥们善意的提醒了我一 ...

  7. 当我谈 "加班有罪" 我在谈什么?

    前言 PS. 本文只描述IT行业. 博客园果真人气比较高,我之前准备写个 "领域驱动系列",然后感觉大家不感兴趣,看来用的人不多,所以一直没动力续,但是昨天写了 [加班有罪] (h ...

  8. VS2013的 Browser Link 引起的问题

    环境:vs2013 问题:在调用一个WebApi的时候出现了错误: 于是我用Fiddler 4直接调用这个WebApi,状态码是200(正常的),JSon里却提示在位置9409处文本非法, 以Text ...

  9. Linux核心源码阅读方法

    首次阅读Linux4.0.5内核源代码时,一脸茫然,它的代码不仅复杂,而且庞大,找不到从哪里开始阅读. 通常Linux会有以下目录 arch 子目录包括所有和体系结构相关的核心代码.它还有更深的子目录 ...

  10. js立即执行函数

    一.JS立即执行函数的写法 方式1.最前最后加括号 (function(){alert(1);}()); 方式2.function外面加括号   (function(){alert(1);})(); ...