hibernate映射继承关系(一):一张表对应一整棵类继承树

2023-11-10

[翻译] hibernate映射继承关系(一):一张表对应一整棵类继承树

2人收藏此文章, 我要收藏发表于1年前(2012-05-22 16:34) , 已有 482次阅读 ,共 0个评论

英文原址

网上这个主题的文章不在少数,这个系列的文章的部分价值在于给出了注解模式(Annotation)的例子。文章易懂,权当增强记忆,捎带着练习下翻译(翻译不当之处请指出)。  

Hibernate中继承关系的简介

java是一种面向对象语言,它可以实现继承关系。然而,继承却是"对象模型-关系模型"不匹配的最显而易见的方面之一。面向对象系统能够轻松的对“is a”和“has a”关系进行建模。而关系模型只能表达两个实体间的"has a"关系。hibernate能够把有关联的表映射为对象,但你需要根据需要来选择不同的映射策略。

Hibernate继承关系映射策略分为三种:一张表对应一整棵类继承树、一个类对应一张表、每一个具体类对应一张表。

之一:一张表对应一整棵类继承树(子类和父类共享同一张表)

假设我们有一个 Person 类及其子类 Employee. 每个类包括如下属性:

1 class Person
2         - firstname
3         - lastname
4  
5 class Employee
6         - joining_date
7         - department_name

在“一张表对应一整棵类继承树这种模式中,继承树上的所有类的数据都存储在一张表上,鉴别器字段(discriminator )是唯一的标识每个类的关键字段。

下面是“一张表对应一整棵类继承树模式的优点和缺点:

优点

这种模式提供了最好的性能,因为即使在深层继承的情况下,检索一条子类数据,也只需要一次select操作。

缺点

对于任何一个子类的变更,比如增删改某字段,都将导致数据库表的变更。 

建表语句

1 CREATE TABLE `person` (
2     `person_id` BIGINT(10) NOT NULL AUTO_INCREMENT,
3     `firstname` VARCHAR(50) NULL DEFAULT NULL,
4     `lastname` VARCHAR(50) NULL DEFAULT NULL,
5     `joining_date` DATE NULL DEFAULT NULL,
6     `department_name` VARCHAR(50) NULL DEFAULT NULL,
7     `discriminator` VARCHAR(20) NOT NULL,
8     PRIMARY KEY (`person_id`)
9 )

PERSON表被用来同时存储 Employee  Person 对象. 

Hibernate 继承: XML 映射 

下面的例子展示了如何用XML方式映射  Employee  Person 实体类

Person.java 

01 package net.viralpatel.hibernate;
02   
03 public class Person {
04   
05     private Long personId;
06     private String firstname;
07     private String lastname;
08   
09     // Constructors and Getter/Setter methods,
10 }

Employee.java

01 package net.viralpatel.hibernate;
02   
03 import java.util.Date;
04   
05 public class Employee extends Person {
06   
07     private Date joiningDate;
08     private String departmentName;
09   
10     // Constructors and Getter/Setter methods,
11 }

Person.hbm.xml

01 <?xml version="1.0" encoding="UTF-8"?>
02 <!DOCTYPE hibernate-mapping PUBLIC
03         "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
04         "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
05   
06 <hibernate-mapping package="net.viralpatel.hibernate">
07   
08     <class name="Person" table="PERSON" discriminator-value="P">
09         <id name="personId" column="PERSON_ID">
10             <generator class="native" />
11         </id>
12   
13         <discriminator column="DISCRIMINATOR" type="string" />
14   
15         <property name="firstname" />
16         <property name="lastname" column="lastname" />
17   
18         <subclass name="Employee" extends="Person" discriminator-value="E">
19                 <property name="departmentName" column="department_name" />
20                 <property name="joiningDate" type="date" column="joining_date" />
21         </subclass>
22     </class>
23 </hibernate-mapping>

注意这里只定义了一个 hibernate 映射文件 Person.hbm.xml.

Person  Employee 类都定义在这同一个文件中.

<discriminator> 标签用来指定鉴别器列,包括列名和类型.

<subclass> 标签用于映射子类 Employee. 注意我们没有用常规的 <class>标签来映射 Employee ,因为它位于继承关系树下端。

Person 类的鉴别器的值被指定为 “P” ,相应的 Employee “E”,这样Hibernate将要持久化person  employee时,相应的“P”“E”将被置入鉴别器字段。

 Hibernate 继承: 注解映射

 下面的例子展示了如何用JPA注解方式来映射 Employee  Person 实体类。

 Person.java 

01 package net.viralpatel.hibernate;
02   
03 import javax.persistence.Column;
04 import javax.persistence.DiscriminatorColumn;
05 import javax.persistence.DiscriminatorType;
06 import javax.persistence.DiscriminatorValue;
07 import javax.persistence.Entity;
08 import javax.persistence.GeneratedValue;
09 import javax.persistence.Id;
10 import javax.persistence.Inheritance;
11 import javax.persistence.InheritanceType;
12 import javax.persistence.Table;
13   
14 @Entity
15 @Table(name = "PERSON")
16 @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
17 @DiscriminatorColumn(
18     name="discriminator",
19     discriminatorType=DiscriminatorType.STRING
20 )
21 @DiscriminatorValue(value="P")
22 public class Person {
23   
24     @Id
25     @GeneratedValue
26     @Column(name = "PERSON_ID")
27     private Long personId;
28   
29     @Column(name = "FIRSTNAME")
30     private String firstname;
31   
32     @Column(name = "LASTNAME")
33     private String lastname;
34   
35     // Constructors and Getter/Setter methods,
36 }

Person 类是继承树的根类,所以我们使用了下面一些注解使其成为根类。

@Inheritance – 定义一个实体类继承树的继承策略,这个注解只能定义在继承树的根类上。

@DiscriminatorColumn – 用于当@Inheritance 的值被定义为 SINGLE_TABLE  JOINED 时,指定鉴别器列。 此注解只能用于两种类:一、继承树的根类,二、继承树的某子类,并且该子类定义了自己继承策略。

如果在需要鉴别器列的时候,没有使用@DiscriminatorColumn注解,那么鉴别器列的名称将默认为“DTYPE”,类型将默认为“STRING”。

@DiscriminatorValue – 用于指定给定实体类所对应的鉴别器列的具体值。 DiscriminatorValue 注解只能用在具体的实体类中。如果使用了鉴别器列,但是没有使用 DiscriminatorValue 注解,一个鉴别器值生成器将生效并产生一个鉴别器值来代表这个类。如果鉴别器列的类型是 STRING,  鉴别器列的值默认是该类的名称。如果不采用默认值,那么应该在继承树的每个类中都使用该注解。

 Employee.java 

01 package net.viralpatel.hibernate;
02   
03 import java.util.Date;
04   
05 import javax.persistence.Column;
06 import javax.persistence.DiscriminatorValue;
07 import javax.persistence.Entity;
08 import javax.persistence.Table;
09   
10 @Entity
11 @Table(name="PERSON")
12 @DiscriminatorValue("E")
13 public class Employee extends Person {
14   
15     @Column(name="joining_date")
16     private Date joiningDate;
17   
18     @Column(name="department_name")
19     private String departmentName;
20   
21     // Constructors and Getter/Setter methods,
22 }

Employee类是Person类的子类,所以在映射时,使用@DiscriminatorValue注解来定义鉴别器的值,此例中,“E”将被置入鉴别器列。 

 MainClass

 package net.viralpatel.hibernate;

01 import java.util.Date;
02   
03 import org.hibernate.Session;
04 import org.hibernate.SessionFactory;
05   
06 public class Main {
07   
08     public static void main(String[] args) {
09   
10         SessionFactory sf = HibernateUtil.getSessionFactory();
11         Session session = sf.openSession();
12         session.beginTransaction();
13   
14         Person person = new Person("Steve""Balmer");
15         session.save(person);
16   
17         Employee employee = new Employee("James""Gosling""Marketing"new Date());
18         session.save(employee);
19   
20         session.getTransaction().commit();
21         session.close();
22   
23     }
24 }

Main class  用来持久化  Person          Employee类的实例。注意两个类都存储在PERSON表中,鉴别器列用于区分两个实体。

 输出结果

1 Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, discriminator) values (?, ?, 'P')
2 Hibernate: insert into EMPLOYEE (FIRSTNAME, LASTNAME, department_name, joining_date, discriminator) values (?, ?, ?, ?, 'E')

 

需要例子中完整代码的,原文连接中提供有下载。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

hibernate映射继承关系(一):一张表对应一整棵类继承树 的相关文章

随机推荐

  • 《Perl语言入门》读书笔记(四)子程序

    1 子程序 1 1 定义子程序 使用关键字sub开头 在写上子程序名 字母 数字和下划线组成 不能以数字开头 大括号框柱子程序主体 子程序可以定义在文件的任意位置 为了方便代码阅读 一般建议放在开头或结尾处 sub marine n 1 全
  • WebSocket的使用指南---前端

    1 WebSocket概述 WebSocket 是 HTML5 开始提供的一种浏览器与服务器间进行全双工通讯的网络技术 WebSocket 通信协议于2011年被IETF定为标准RFC 6455 WebSocketAPI 被 W3C 定为标
  • String

    String是一个对象 不是基本数据类型 String的特点 字符串对象一旦初始化 便不能被修改 改变的只是引用型变量的指向 例如 String str abc String str ert abc 依然存在 只是str的指向变了 Stri
  • Mysql系列 - 第4天:DDL常见操作汇总

    这是Mysql系列第4篇 环境 mysql5 7 25 cmd命令中进行演示 DDL Data Define Language数据定义语言 主要用来对数据库 表进行一些管理操作 如 建库 删库 建表 修改表 删除表 对列的增删改等等 文中涉
  • 机器学习中的特征变量及处理总结

    文章目录 1 定性特征变量 1 1 定类变量处理 1 2 定序变量处理 2 定量特征变量 3 总结 牢记一句话 数据和特征决定了机器学习的上限 而模型和算法只是逼近这个上限而已 机器学习的根本目标 就是用数据的特征变量去对目标变量进行预测
  • Github 榜首!B 站疯传!程序员思维导图 48 张!!!

    介绍在下面 整个内容包括 程序员史上最强编程思维导图 48 张 800 份求职简历模板 我写的 图解算法小册 解析 150 道高频算法面试题目 25k star Github 榜首项目 资料获取地址 无套路 直接可以下载 Github 榜首
  • Jmeter快速上手之接口测试

    目录 1 前言 2 简介 3 安装 4 环境变量 4 1 Windows环境 4 2 Mac环境 5 启动程序 6 目录说明 7 操作示例 7 1 Get请求 7 2 Post请求 7 3 依赖请求 1 前言 压测工具 Jmeter 除了可
  • 什么是接口?

    1 什么是接口 接口是一种特殊的内部类 它里面的所有方法都没有实现 2 接口的特点 1 接口中成员默认访问修饰符都是public 即便你不写 2 定义接口必须interface关键字完成 3 接口中可以定义变量 但是变量必须有固定的修饰符修
  • JUC并发编程--------线程安全篇

    目录 什么是线程安全性问题 如何实现线程安全 1 线程封闭 2 无状态的类 3 让类不可变 4 加锁和CAS 并发环境下的线程安全问题有哪些 1 死锁 2 活锁 3 线程饥饿 什么是线程安全性问题 我们可以这么理解 我们所写的代码在并发情况
  • java自引用/类的递归调用问题

    Java的自引用问题 什么是自引用 递归调用 代码示例和分析 自引用情况 类比C 什么是自引用 递归调用 在编写代码的过程中 我们经常看到类中出现该类的声明 示例 class A int data A a 这种情况就被称为自引用 代码示例和
  • Android架构项目代码结构规范--组件化代码

    前言 组件化和插件化有什么区别 虽说网上有很多文章但是讲清的聊聊无几 这也是这篇文章的由来 大方向 组件化是一个项目主管设计管理项目架构方案 而插件化有商务上的合作和局部功能热更换修复等 小方向 如果是公司app合作 组件化也就是插件化作为
  • CLion Bug集合1:windows下导入openssl库方法以及踩过的坑

    系统 win10 64位 工具链 MinGW IDE CLion openssl库下载 下载方法 主要有两种方式 本文主要讲解方式1 方式1 下载地址 2022 6 1补充 该方法的动态库是MinGW64位用的 32位见方法2 方式2 编译
  • linux常用命令案例总结wc,top,free,df -h,head,sed,awk,netstat -antp,ps -aux, ethtool eth0

    1 wc的使用 统计一个目录下的文件个数 root localhost etc cd var log root localhost log ll grep wc l 53 root localhost log 拓展 关于命令wc的使用 wc
  • 使用冻结层进行迁移学习

    使用冻结层进行迁移学习 在yolov5的训练过程中 作者介绍了如何使用冻结层实现迁移学习的策略 具体可以参考官方话题 Transfer Learning with Frozen Layers Issue 1314 ultralytics y
  • JS中的Date数据类型

    JS的Date数据类型 在JavaScript中 Date数据类型用于处理日期和时间 它可以表示自1970年1月1日00 00 00 UTC 协调世界时 以来的毫秒数 Date对象在许多应用程序中都非常有用 例如在Web应用程序中显示当前时
  • Python实现HBA混合蝙蝠智能算法优化循环神经网络回归模型(LSTM回归算法)项目实战

    说明 这是一个机器学习实战项目 附带数据 代码 文档 视频讲解 如需数据 代码 文档 视频讲解可以直接到文章最后获取 1 项目背景 蝙蝠算法是2010年杨教授基于群体智能提出的启发式搜索算法 是一种搜索全局最优解的有效方法 该算法基于迭代优
  • eMMC简介

    eMMC是embedded MultiMediaCard的简称 MultiMediaCard 即MMC 是一种闪存卡 Flash Memory Card 标准 它定义了MMC的架构以及访问Flash Memory的接口和协议 而eMMC则是
  • 全屏dialog

    下面是iOS里面做全屏Dialog的代码 调用show时Dialog会覆盖当前的controller 全屏显示 可以用来做蒙板效果 欢迎转载 转载请注明出处 http blog csdn net tadican article detail
  • Python中的装饰器是什么?装饰器是如何工作的?

    Python很早就引入了装饰器 在PEP 318中 作为一种简化函数和方法定义方式的机制 这些函数和方法在初始定义之后必须进行修改 这样做的最初动机之一是 使用classmethod和staticmethod等函数来转换方法的原始定义 但是
  • hibernate映射继承关系(一):一张表对应一整棵类继承树

    翻译 hibernate映射继承关系 一 一张表对应一整棵类继承树 2人收藏此文章 我要收藏发表于1年前 2012 05 22 16 34 已有 482次阅读 共 0个评论 英文原址 网上这个主题的文章不在少数 这个系列的文章的部分价值在于