【SSH快速进阶】——Hibernate继承映射:每棵继承树映射一张表
2016-02-18 22:22
459 查看
我们都知道,Hibernate最大的一个优点就是使开发更加“面向对象”,类与类之间有继承关系,Hibernate中也对这种继承关系提供了映射的封装。
Hibernate为继承映射提供了三种策略
1、每棵继承树使用一张表
2、每个子类使用一张表
3、每个具体类使用一张表
本文对第一种策略进行说明。
场景
如下类图
上图中Pig类和Bird类继承Animal类,每棵继承树对应一张表,即在同一棵继承树中,所有的类的对象信息(记录)共同存放到一张表中,要判断某条记录属于哪个对象,需要在表中添加一个字段进行区分(比如下表的Type字段)。
(表 1)
配置
PO对象
Animal.java
Bird.java
Pig.java
映射文件
配置映射文件时,父类还用
Extends.hbm.xml
映射文件中的
启动程序执行的建表语句为:
插入测试
插入结果为:
插入父类(Animal)时,默认把类名当做type了
查询测试
load查询
根据配置,鉴别值(表中的type)在存储的时候会自动存储,在加载的时候也会根据鉴别值映射取得相应的对象。
比如查询id为1的那条数据,既可以用Pig查询,也可以用Animal查询。
用session.load(Pig.class, 1)查询:
用session.load(Animal.class, 1)查询:
执行结果都为:
如果用load方法查询的话,默认是不支持多态查询(hibernate在加载数据的时候会自动鉴别类的真正类型)的,因为load默认支持lazy(懒加载),所以上面的pig只是Animal的代理,因此用instanceof也就判断不出来pig的类型,如下:
运行结果为:
想要支持多态查询也简单,在配置文件中标签后加lazy=”false”即可,禁止懒加载就OK了。
get查询
get查询支持多态查询:
运行结果:
hql查询
总结
这种映射方式可以把多个类放在一张表中,但是粒度比较粗,有冗余字段;但又是因为多个类的相关记录都存放在一张表中,查询时不用关联,因此效率较高。
【 转载请注明出处——胡玉洋《【SSH快速进阶】——Hibernate继承映射:每棵继承树映射一张表》】
Hibernate为继承映射提供了三种策略
1、每棵继承树使用一张表
2、每个子类使用一张表
3、每个具体类使用一张表
本文对第一种策略进行说明。
场景
如下类图
上图中Pig类和Bird类继承Animal类,每棵继承树对应一张表,即在同一棵继承树中,所有的类的对象信息(记录)共同存放到一张表中,要判断某条记录属于哪个对象,需要在表中添加一个字段进行区分(比如下表的Type字段)。
(表 1)
配置
PO对象
Animal.java
[code]public class Animal { private int id; private String name; private boolean sex; //getter、setter }
Bird.java
[code]public class Bird extends Animal{ private int height; //getter、setter }
Pig.java
[code]public class Pig extends Animal{ private int weight; //getter、setter }
映射文件
配置映射文件时,父类还用
<class>标签来定义即可;添加的区分字段(比如上面表1中的Type字段)需要用
<discriminator>标签来定义;用
<subclass>标签定义两个子类,与父类“合并”在同一张表里,子类的特有属性用
<property>属性定义即可。
Extends.hbm.xml
[code]<hibernate-mapping package="com.danny.hibernate"> <class name="Animal"> <id name="id"> <generator class="native"/> </id> <discriminator column="type" type="string"></discriminator> <property name="name"/> <property name="sex"/> <subclass name="Bird" discriminator-value="B"> <property name="height"></property> </subclass> <subclass name="Pig" discriminator-value="P"> <property name="weight"></property> </subclass> </class> </hibernate-mapping>
映射文件中的
<subclass>标签还可以与标签同级,但是要加上属性extends,属性值为父类全路径名称。
启动程序执行的建表语句为:
[code]drop table if exists Animal create table Animal (id integer not null auto_increment, type varchar(255) not null, name varchar(255), sex bit, height integer, weight integer, primary key (id))
插入测试
[code]session=HibernateUtils.getSession(); session.beginTransaction(); Pig pig=new Pig(); pig.setName("小猪猪"); pig.setSex(true); pig.setWeight(200); session.save(pig); Bird bird=new Bird(); bird.setName("小鸟鸟"); bird.setSex(false); bird.setHeight(100); session.save(bird); Animal animal=new Animal(); animal.setName("小动物"); animal.setSex(false); session.save(animal); session.getTransaction().commit();
插入结果为:
插入父类(Animal)时,默认把类名当做type了
查询测试
load查询
根据配置,鉴别值(表中的type)在存储的时候会自动存储,在加载的时候也会根据鉴别值映射取得相应的对象。
比如查询id为1的那条数据,既可以用Pig查询,也可以用Animal查询。
用session.load(Pig.class, 1)查询:
[code]session.beginTransaction(); Pig pig=(Pig)session.load(Pig.class, 1); System.out.println(pig.getName()); session.getTransaction().commit();
用session.load(Animal.class, 1)查询:
[code]session.beginTransaction(); Animal pig=(Animal)session.load(Animal.class, 1); System.out.println(pig.getName()); session.getTransaction().commit();
执行结果都为:
[code]小猪猪
如果用load方法查询的话,默认是不支持多态查询(hibernate在加载数据的时候会自动鉴别类的真正类型)的,因为load默认支持lazy(懒加载),所以上面的pig只是Animal的代理,因此用instanceof也就判断不出来pig的类型,如下:
[code]session=HibernateUtils.getSession(); session.beginTransaction(); Animal animal=(Animal)session.load(Animal.class, 1); if(animal instanceof Pig){ System.out.println(animal.getName()); }else if(animal instanceof Bird){ System.out.println(animal.getName()); }else{ System.out.println("既不是小猪猪也不是小鸟鸟"); } session.getTransaction().commit();
运行结果为:
[code]既不是小猪猪也不是小鸟鸟
想要支持多态查询也简单,在配置文件中标签后加lazy=”false”即可,禁止懒加载就OK了。
get查询
get查询支持多态查询:
[code]session=HibernateUtils.getSession(); session.beginTransaction(); Animal animal=(Animal)session.get(Animal.class, 1); if(animal instanceof Pig){ System.out.println(animal.getName()); }else if(animal instanceof Bird){ System.out.println(animal.getName()); }else{ System.out.println("既不是小猪猪也不是小鸟鸟"); } session.getTransaction().commit();
运行结果:
[code]既不是小猪猪也不是小鸟鸟
hql查询
[code]session=HibernateUtils.getSession(); session.beginTransaction(); List animalList=session.createQuery("from Animal").list(); for(Iterator iter=animalList.iterator();iter.hasNext();){ Animal animal=(Animal)iter.next(); System.out.println(animal.getName()); } session.getTransaction().commit();
总结
这种映射方式可以把多个类放在一张表中,但是粒度比较粗,有冗余字段;但又是因为多个类的相关记录都存放在一张表中,查询时不用关联,因此效率较高。
【 转载请注明出处——胡玉洋《【SSH快速进阶】——Hibernate继承映射:每棵继承树映射一张表》】
相关文章推荐
- MVC快速分页
- [iOS] 输入框高度随输入内容变化
- [转]小品:宋江同志在梁山泊招安动员大会上的讲话
- MySQL知识(三)——数据类型
- js动画(3)——缓冲动画
- 从今天开始颠覆对世界的认知
- 最详细的Log4j使用教程
- [转]论acm与泡妞
- [转]论acm与泡妞
- css3,background-clip/background-origin的使用场景,通俗讲解
- 【003】Mac在命令行下下载文件
- 简介ImageLoader(一)
- Activity的启动模式解析
- UVaOJ10282
- c语言:【顺序表】静态顺序表的删除指定位置元素Erase、删除指定元素Remove
- LeetCode_1_TwoSum(Java Code)
- Windows窗口及对话框
- 基于zepto或jquery的手机端弹出框成功,失败,加载特效
- 用EL表达式取List<Map<String, Object>>map的值(查阅了很久,总结一下)
- 二叉树的深度&判断一棵二叉树是否是平衡二叉树&110. Balanced Binary Tree