【Hibernate 5】继承映射配置及多态查询
一、继承实现的三种策略
1.1,单表继承。每棵类继承树使用一个表(table per class hierarchy) ——>本文主要介绍的继承策略
类继承树对应多个类,要把多个类的信息存放在一张表中,必须有某种机制来区分哪些记录是属于哪个类的。这种机制就是,在表中添加一个字段,用这个字段的值来进行区分。用hibernate实现这种策略的时候,有如下步骤:
1,父类用普通的<class>标签定义,在父类中定义一个discriminator,即指定这个区分的字段的名称和类型
如:<discriminator column=”XXX” type=”string”/>
2,子类使用<subclass>标签定义,在定义subclass的时候,需要注意如下几点:Subclass标签的name属性是子类的全路径名;在Subclass标签中,用discriminator-value属性来标明本子类的discriminator字段(用来区分不同类的字段)的值;Subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系),也可以与class标签平行。 当subclass标签的定义与class标签平行的时候,需要在subclass标签中,添加extends属性,里面的值是父类的全路径名称。子类的其它属性,像普通类一样,定义在subclass标签的内部。
PS:唯一字段隔离,也就是所谓的type,通过type确定子类的类型,每条数据中包含了需要的所有信息字段
1.2,每个具体类一个表(table per concrete class)(有一些限制)
这种策略使用joined-subclass标签来定义子类。父类、子类,每个类都对应一张数据库表。在父类对应的数据库表中,实际上会存储所有的记录,包括父类和子类的记录;在子类对应的数据库表中,这个表只定义了子类中所特有的属性映射的字段。子类与父类,通过相同的主键值来关联。实现这种策略的时候,有如下步骤:
1,父类用普通的<class>标签定义即可,父类不再需要定义discriminator字段
2,子类用<joined-subclass>标签定义,在定义joined-subclass的时候,需要注意如下几点:Joined-subclass标签的name属性是子类的全路径名;Joined-subclass标签需要包含一个key标签,这个标签指定了子类和父类之间是通过哪个字段来关联的。如:<key column=”PARENT_KEY_ID”/>,这里的column,实际上就是父类的主键对应的映射字段名称。
3,Joined-subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系),也可以与class标签平行。 当Joined-subclass标签的定义与class标签平行的时候,需要在Joined-subclass标签中,添加extends属性,里面的值是父类的全路径名称。子类的其它属性,像普通类一样,定义在joined-subclass标签的内部。
PS:表隔离,每个表中都只有属于自身对应的属性,如果要获取完整的数据,则需要通过外键联合查询
1.3,具体表继承。每个子类一个表(table per subclass)
这种策略使用union-subclass标签来定义子类。每个子类对应一张表,而且这个表的信息是完备的,即包含了所有从父类继承下来的属性映射的字段(这就是它跟joined-subclass的不同之处,joined-subclass定义的子类的表,只包含子类特有属性映射的字段)。实现这种策略的时候,有如下步骤:
1,父类用普通<class>标签定义即可
2,子类用<union-subclass>标签定义,在定义union-subclass的时候,需要注意如下几点:Union-subclass标签不再需要包含key标签(与joined-subclass不同);Union-subclass标签,既可以被class标签所包含(这种包含关系正是表明了类之间的继承关系),也可以与class标签平行。 当Union-subclass标签的定义与class标签平行的时候,需要在Union-subclass标签中,添加extends属性,里面的值是父类的全路径名称。子类的其它属性,像普通类一样,定义在Union-subclass标签的内部。这个时候,虽然在union-subclass里面定义的只有子类的属性,但是因为它继承了父类,所以,不需要定义其它的属性,在映射到数据库表的时候,依然包含了父类的所有属性的映射字段。
PS:表隔离,与每个具体类不同的是,这种策略只会为每个具体的子类生成表单,而在每个表单里,既包含了父类的属性,又包含了自身的属性。当需要查询一条完整数据的时候,不需要联合外键!
二、实例介绍继承映射
2.1,建立实体类和映射
Animal类:
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.hibernate; public class Animal { private int id; private String name; private boolean sex; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public boolean isSex() {
return sex;
} public void setSex(boolean sex) {
this.sex = sex;
}
}
</span>
Bird类:
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.hibernate; public class Bird extends Animal { private int height; public int getHeight() {
return height;
} public void setHeight(int height) {
this.height = height;
}
}
</span>
Pig类:
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.hibernate; public class Pig extends Animal { private int weight; public int getWeight() {
return weight;
} public void setWeight(int weight) {
this.weight = weight;
}
}
</span>
映射文件:
<span style="font-family:KaiTi_GB2312;font-size:18px;"><?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.angel.hibernate.Animal" table="t_animal" lazy="false">
<id name="id">
<generator class="native" />
</id>
<!-- 加入鉴别标签,且必须放在id后面 -->
<discriminator column="type" type="string"/>
<property name="name" />
<property name="sex" type="boolean" /> <subclass name="com.angel.hibernate.Pig" discriminator-value="P">
<property name="weight" />
</subclass>
<subclass name="com.angel.hibernate.Bird" discriminator-value="B">
<property name="height" />
</subclass>
</class> </hibernate-mapping> </span>
2.2,测试类
<span style="font-family:KaiTi_GB2312;font-size:18px;">package com.angel.hibernate; import org.hibernate.Session; import junit.framework.TestCase; public class test_extend extends TestCase { public void testSave() {
Session session = null;
try {
// 创建session对象
session = HibernateUtils.getSession();
// 开启事务
session.beginTransaction(); Pig pig = new Pig();
pig.setName("daddy pig");
pig.setSex(true);
pig.setWeight(200);
session.save(pig); Bird bird = new Bird();
bird.setName("mummy bird");
bird.setSex(true);
bird.setHeight(100);
session.save(bird); session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
} finally {
HibernateUtils.closeSession(session);
}
} public void testLoad(){
Session session=null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Animal a = (Animal)session.load(Animal.class, 1);
//load默认支持lazy,所以我们看到的是Animal的代理,采用instanceof无法鉴别出真正的类型Pig
//如果想要load支持多态查询,则需要将lazy值设置为false
if (a instanceof Pig) {
System.out.println(a.getName());
}else {
System.out.println("不是猪!");
}
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
} }
</span>
三、多态查询
多态查询:hibernate在加载数据的时候,能够采用instancof鉴别出其真正的类型
在Hibernate中,支持多台查询的有:get、Hql。而对于load,因为其默认支持延迟加载lazy,所以它不支持多态查询,返回的只是一个代理值。如果想要让load支持多态查询,则需要在配置文件中将其lazy属性设置为false。
四、总结
继承映射在实际运用中还是很广泛中,在做这个例子的时候,突然想起来多租户数据隔离的三个策略,其实跟这个差不多。额,说明我脑袋里还是装东西了嘛。然后对于继承映射的三种策略,可以看出的是,单表继承是比较简单而且效率高的,只需要维护一个表。而具体表策略则需要进行外键维护等,相对来说单表继承是一个比较好的选择!
【Hibernate 5】继承映射配置及多态查询的更多相关文章
- 【JavaEE】Hibernate继承映射,不用多态查询只查父表的方法
几个月前,我在博问里面发了一个问题:http://q.cnblogs.com/q/64900/,但是一直没有找到好的答案,关闭问题以后才自己解决了,在这里分享一下. 首先我重复一下场景,博问里面举的动 ...
- hibernate笔记--继承映射关系的三种实现方式
单表继承映射(一张表): 假设我们现在有三个类,关系如下: Person类有两个子类Student和Teacher,并且子类都具有自己独有的属性.这种实体关系在hibernate中可以使用单表的继承映 ...
- Hibernate之继承映射
1. Hibernate支持三种继承映射策略: –使用 subclass进行映射:将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态. –使用 j ...
- 初识Hibernate之继承映射
前面的两篇文章中,我们介绍了两张表之间的各种相互关联映射关系,但往往我们也会遇到两张表甚至多张表之间共有着多个相同的字段.例如: 如图,student表和teacher表共同具有id,nam ...
- Hibernate框架 主配置文件 Hibernate.cfg.xml 映射配置 说明
1 主配置文件 Hibernate.cfg.xml 主配置文件中主要配置:数据库连接信息.其他参数.映射信息! 常用配置查看源码: hibernate-distribution-3.6.0.Final ...
- Hibernate的继承映射
对象模型示例: 继承映射的实现方式有以下三种: (一)每棵类继承树一张表 (二)每个类一张表 (三)每个子类一张表 (一)每棵类继承树一张表 关系模型如下: 映射文件如下: <hibernate ...
- hibernate中继承映射保存
1 简单继承映射,在子类上进行映射配置,可以将父类属性直接配置在子类映射文件中. 简单例子如下:teacher类继承自Person类. public class Person { private in ...
- 继承映射关系 subclass的查询
Person大类的映射文件配置 1 <hibernate-mapping package="com.zh.hibernate.subclass"> <class ...
- Hibernate一对一关联映射配置
一.一对一关联 Hibernate提供了两种映射一对一关联关系的方式:按照外键映射和按照主键映射.下面以员工账号和员工档案表为例,介绍这两种映射方式,并使用这两种映射方式分别完成以下持久化操作: (1 ...
随机推荐
- 算法的上帝——Donald E.Knuth(转)
开始介绍前先膜拜之~ 密尔沃基市,是美国威斯康辛州最大的城市.1938年1月10日,圣诞刚过不久,密尔沃基市民像往常一样平静地生活着.咖啡店里,有人在议论着罗斯 福总统的救市新政策,有人在议论着到底该 ...
- MongoDB 3.0.6的主,从,仲裁节点搭建
在MongoDB所在路径创建log和data目录mkdir logmkdir data 在data目录下 创建master.slaver.arbiter路径 mkdir master mkdir sl ...
- window.print实现打印特定控件或内容
window.print打印指定div 首先我们可以把要打印的内容放在div中,然后用下面的代码进行打印. <html> <head> <script language= ...
- unsigned char 转字符串:
通常送显示的都是字符串,对于int long float转字符串有对应的函数,还有sprintf进行格式输出,对于嵌入式和单片机大多都用unsigned char型变量,转字符串需要自己编写函数,需要 ...
- 如何使用javadoc
package com.frank.chapter1; // object.Documentation1.java // TIJ4 Chapter Object, Exercise 13 - 1 /* ...
- UITouch 触摸事件处理(实例)
来源:http://www.open-open.com/lib/view/open1341882439838.html 1. UITouch 的主要方法: - (void)touchesBegan:( ...
- ISO14229系列之一:简介
作者:autogeek 原文链接:http://www.cnblogs.com/autogeek/p/4458591.html 前言 由于工作中经常用到ISO-14229,因此决定对该协议做个总体介绍 ...
- [ActionScript3.0] 深表复制
function clone(obj:Object):Object{ var byteArray:ByteArray = new ByteArray(); byteArray.writeObject( ...
- CRM 2016 自动保存 Save event arguments
Save event arguments (client-side reference) Applies To: Dynamics CRM 2016, Dynamics CRM Online In ...
- crm SSRS 报表 导出格式控制
如果是使用的网页嵌入ReportView的方式的,可以在aspx上加入js来控制导出格式: <script src="js/jquery-1.9.0.js"></ ...