hibernate——继承关系以及三个subclass标签的区别
Java类中有继承关系,相应的在hibernate中,也有继承关系,子类反应到数据库中,就有多种实现形式了,子类和父类可以映射到同一张表中,子类也可以单独映射成一张表,但是用不同的标签实现,子类表和父类表的关系也不同。在映射文件中,有三个标签可以实现继承关系,分别是:subclass、joined-subclass、union-subclass,先陈述一下这三个标签的区别:
subclass标签就是为子类嵌入父类的表中而设计的,而且要指定鉴别器,即用subclass一定要有判断类型的一个列,鉴别器指定记录属于哪个类型。但是subclass也提供了为子类设置单独的表的功能,即join标签。但是不管是内嵌表还是外部表,都得指定鉴别器。
joined-subclass标签,提供的功能是只能为子类设定外部表,而且没有鉴别器,即子类一张表,父类一张表,子类以父类的主键为外键。父类对应的表中,没有判断类型的列。
注意:这两个标签不能混用,若是只想要内嵌表,或者是既想要有内嵌表,又想要外部表,又或者是只想要外部表,那么只能使用subclass标签,需要注意的是,不论哪种方式,都要指定鉴别器,即父类对应的表中,一定有一个判断类型的列;而若是只想要外部表,又不想在父类对应的表中,要那个判断类型的列,那么只能使用join-subclass
union-subclass是将父类中的属性,添加到子类对应的表中去了。包括父类中的外键。union-class和前两个的区别就在于外键的不同,前两个标签,如果子类有单独对应的表的话,这个表的外键是其父类中的主键,而使用union-class,子类对应的表中的外键则和父类的外键是一样的,因为子类把父类继承的属性,也加到了自己的表当中。这样子类和父类的地位就相当了。不过这不是一种好的理解方式。如果是这样的话,那么就可以把父类设为抽象的类,并且在映射文件中,把父类设置为abstract="true",那么就不会再数据库中生成父类对应的表了,父类就只起到一个抽象的作用了。
下面列举员工和部门的例子说明,假设员工类还有两个子类:一个是技术人员,一个是销售人员:
- public class Employee {
- private int id;
- private String name;
- private Department depart;
- ……//set/get方法
- }
- public class Skiller extends Employee {
- private String skill;
- ……//set/get方法
- }
- public class Saler extends Employee {
- private String sale;
- private int age;
- ……//set/get方法
- }
- public class Department {
- private int id;
- private String name;
- private Set<Employee> emps;
- ……//set/get方法
- }
部门类的映射文件:
- <class name="Department">
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <set name="emps" inverse="true">
- <key column="depart_id"/>
- <one-to-many class="Employee"/>
- </set>
- </class>
(1)下面关键是员工类的映射文件,我们先来看使用subclass标签的情况:
- <class name="Employee" discriminator-value="0">
- <id name="id">
- <generator class="native"/>
- </id>
- <discriminator column="type" type="int"/><!-- 指定了鉴别器 -->
- <property name="name"/>
- <many-to-one name="depart" column="depart_id"/>
- <subclass name="Skiller" discriminator-value="1">
- <property name="skill"/>
- </subclass>
- <subclass name="Saler" discriminator-value="2">
- <property name="sale"/>
- </subclass>
- </class>
这种情况就是所谓的将整个继承树映射到同一个表当中,即子类的信息,全部映射到了父类对应的表中。注意,一定要指定鉴别器,它的作用是在父类的映射表中,添加了一个type的列,用来鉴别员工是属于哪个子类,并且在每个类的标签中要指定鉴别器值,如上例中用0表示是普通的员工,用1表示技术人员,用2表示销售人员。我们可以看看创建表的ddl语句:
- CREATE TABLE `employee` (
- `id` int(11) NOT NULL,
- `type` int(11) NOT NULL,
- `name` varchar(255) DEFAULT NULL,
- `depart_id` int(11) DEFAULT NULL,
- `skill` varchar(255) DEFAULT NULL,
- `sale` varchar(255) DEFAULT NULL,
- PRIMARY KEY (`id`),
- KEY `FK4AFD4ACE972E0614` (`depart_id`),
- CONSTRAINT `FK4AFD4ACE972E0614` FOREIGN KEY (`depart_id`) REFERENCES `department` (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=gbk
用这种方式有缺点有优点,缺点是在表中,会有很多的空值,假如又有了新的子类,那么就要修改表的结构,并且相应的空值会更多;优点是所有信息整合到一张表中,查询的效率高。
下面再来看subclass标签的第二种用法:
- <class name="Employee" discriminator-value="0"><!-- discriminator-value="0" -->
- <id name="id">
- <generator class="native"/>
- </id>
- <discriminator column="type" type="int"/><!-- 指定了鉴别器 -->
- <property name="name"/>
- <many-to-one name="depart" column="depart_id"/>
- <subclass name="Skiller" discriminator-value="1">
- <property name="skill"/>
- </subclass>
- <subclass name="Saler" discriminator-value="2">
- <join table="saler">
- <key column="emp_id"/>
- <property name="sale"/>
- </join>
- </subclass>
- </class>
改变的地方,主要是Saler类的标签,在subclass标签中用join标签,这样就为Saler子类单独映射了一个saler表,其主键为父类对应的表的主键。而Skiller类还是和父类映射到了一张表中。来看看Saler创建表的ddl语句:
- CREATE TABLE `saler` (
- `emp_id` int(11) NOT NULL,
- `sale` varchar(255) DEFAULT NULL,
- PRIMARY KEY (`emp_id`),
- KEY `FK682490B3F739201` (`emp_id`),
- CONSTRAINT `FK682490B3F739201` FOREIGN KEY (`emp_id`) REFERENCES `employee` (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=gbk
需要注意的一个地方是这个表的外键,外键和主键是一样的,都是父类表的主键。
(2)joined-subclass的使用
- <class name="Employee"><!-- discriminator-value="0" -->
- <id name="id">
- <generator class="native"/>
- </id>
- <property name="name"/>
- <many-to-one name="depart" column="depart_id"/>
- <joined-subclass name="Skiller" table="skiller">
- <key column="emp_id"/>
- <property name="skill"/>
- </joined-subclass>
- <joined-subclass name="Saler" table="saler">
- <key column="emp_id"/>
- <property name="sale"/>
- </joined-subclass>
- </class>
用joined-subclass只能创建为子类单独创建表,子类对应的表的主键和外键都是其父类的主键。注意,joined-subclass不能和subclass混合使用。
(3)union-subclass的使用
- <class name="Employee">
- <id name="id">
- <generator class="hilo"/>
- </id>
- <property name="name"/>
- <many-to-one name="depart" column="depart_id"/>
- <union-subclass name="Skiller" table="skiller">
- <property name="skill"/>
- </union-subclass>
- <union-subclass name="Saler" table="saler">
- <property name="age"/>
- <property name="sale"/>
- </union-subclass>
- </class>
注意,这里主键的生成方式就不能是自增的了,这里用的hilo方式,可以为子类的表分配和父类的表不同的主键。这样每个子类生成了一个表,并且结合了父类中的属性。生成的表的ddl语句为:
- CREATE TABLE `skiller` (
- `id` int(11) NOT NULL,
- `name` varchar(255) DEFAULT NULL,
- `depart_id` int(11) DEFAULT NULL,
- `skill` varchar(255) DEFAULT NULL,
- PRIMARY KEY (`id`),
- KEY `FK4AFD4ACE972E06147ffd86be` (`depart_id`),
- CONSTRAINT `FK4AFD4ACE972E06147ffd86be` FOREIGN KEY (`depart_id`) REFERENCES `department` (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=gbk
注意,这里的外键是部门类对应的表的主键,这是和上面两个标签的区别之处。若是将父类设置为抽象类,并且在class标签中设置abstract="true",那么父类就不会生成对应的表了。
hibernate——继承关系以及三个subclass标签的区别相关推荐
- hibernate继承关系映射方法(三)--每个具体类一张表TPC
TPC:所谓是"每个具体类一张表(table per concrete class)"的意思是:使继承体系中每一个子类都对应数据库中的一张表.每一个子类对应的数据库表都包含了父类的 ...
- hibernate继承关系映射关系方法(二)--每个子类一张表
TPS:所谓"每个子类一张表(Table Per Subclass)":父类一张表,每个子类一张表,父类的表保存公共有信息,子类的表只保存自己特有的信息 这种策略是使用<jo ...
- hibernate继承关系映射方法(一)--共享一张表
对于如下关系: Person.java package com.hust.PO;public class Person {private Integer id;private String name; ...
- java继承 映射_hibernate继承关系映射和java反射机制的运用
转:http://blog.csdn.net/derpvailzhangfan/article/details/1957946 ,感谢博主分享 Notes:hibernate元数据的运用:uuid的概 ...
- hibernate 表关系映射详解之继承关系
举例:亚马逊的网上商城可以卖很多东西,比如说图书,电器,水果等等,那么我们以面向对象的理念去抽象一个商品类,他具有商品的共有属性,比如说上架时间,当前 价格,优惠价格等待,商品可以继承 ...
- Hibernate中的Entity类之间的继承关系之一MappedSuperclass
在hibernate中,Entity类可以继承Entity类或非Entity类.但是,关系数据库表之间不存在继承的关系.那么在Entity类之间的继承关系,在数据库表中如何表示呢? Hibernate ...
- Hibernate继承映射
Hibernate继承映射 在面向对象的程序领域中,类与类之间是有继承关系的,例如Java世界中只需要extends关键字就可以确定这两个类的父子关系,但是在关系数据库的世界中,表与表之间没有任何关键 ...
- web进修之—Hibernate 继承映射(5)
先看三个类的继承关系,Payment是父类,CashPayment和CreditCardPayment是Payment的子类: view plaincopy to clipboardprint pub ...
- hibernate 继承映射
在域模型中,类与类之间除了关联关系和聚集关系,还可以存在继承关系,在下图所示的域模型中,Deparment类和Employee类之间为一对多的双向关联关系,Employee类有两个子类:Skiller ...
- JPA和Hibernate的关系
转载自:https://www.cnblogs.com/amoyzhu/p/5937717.html JPA Java Persistence API,是Java EE 5的标准ORM接口,也是ejb ...
最新文章
- BC30138: 无法在路径“C:\WINDOWS\TEMP\”中创建临时文件: 拒绝访问。
- HTML 元素居中的方法
- log4net环境配置
- (zt)说说大型高并发高负载网站的系统架构
- 注解形式控制器 数据验证,类型转换
- NachOS简述和源文件
- 在Mac上安装Linux的行为是否应该被鄙视?
- Ubuntu上面安装Mongo
- 【GPT-3】除了缺少点创意,GPT-3写出了及格的大学毕业论文,只需20分钟
- 7. where loop
- javascript+Java 实现MD5加密登录密码
- AAC音频的解码算法
- Android混淆和加固详解
- 心电信号越界怎么回事_一种心电信号处理方法
- 高效人士的七个管理习惯
- python pyinstaller使用方法_【python快手菜】pyinstaller使用指南
- PostScript 与 Encapsulated PostScript
- k8s.gcr.io、gcr.io仓库的镜像下载
- 关于pd.read_csv() 读数据的注意事项
- 如何使用CAD软件来修改表格中CAD字体颜色?
热门文章
- 疫情肆虐下,程序员们都在哪里?
- matlab从mp4文件中提取音频,如何提取mp4视频中的音频文件 将视频转换为MP3音频...
- POI 报错问题:Merged region A15 must contain 2 or more cells
- win10用户名与计算机名字一样,win10电脑账户名和其他信息怎么更改
- jQuery boxy
- 蛋白质ph稳定性计算机模拟,蛋白质分子设计.ppt
- 【软件技巧】【截图】浏览器自带的全网页截图工具
- VS2019的C++项目如何查看源文件(.h,.cc.cpp等)所在的工程
- unity, Animation crossfade需要两动画在时间上确实有交叠
- 论文写作,word首页脚注不显示编号