【Hibernate步步为营】--继承映射具体解释

上篇文章讨论了多对多映射,在使用多对多映射时重点是使用<many-to-many>标签,并在标签的两端加入外键这样在生成关系时会创建两个关系之间的关系表,通过关系表来维护它们之间的关系,另外对于单向和双向的差别是在映射的哪一端加入标签的问题。在面向对象中非常重要的一个特性就是继承,继承实现了代码的复用,并且Hibernate把基本上全部的对象模型进行了映射封装,当中就包含继承映射,接下来就具体讨论。

一、继承映射

继承是面向对象非常重要的特性,它实现了代码的服用,在关系模型中相同也有继承关系,这样的继承关系事实上能够看做是一种枚举关系,一种类型中能够枚举出非常多子类型,这些子类型和父对象形成了继承关系,能够对其进行枚举的大部分都能够看做是一种继承映射,所以这样的枚举关系能够看做是继承映射,比如动物就是一种抽象类,它是其他动物猪、猫等的父类,它们之间就是一种继承关系,例如以下图:

这样的继承映射在转化为关系模型后会生成一张表,那么这张表是怎样区分这两种类型的呢?用的是关系字段,须要在表中加入类型字段,使用keyword来标明对象的类型。所以上图中的对象模型相应的表结构例如以下:

在生成表结构时,须要加入相应的字段类型,所以须要在映射文件里加入相应的映射鉴别器,这里就须要使用discriminator-value属性。

1.1、类文件

类文件里没有须要注意的地方,在编写时注意之间的继承关系就可以。

清单一:Animal类代码,仅仅须要加入主要的属性。

package com.src.hibernate;

public class Animal {

	//id号
	private int id;
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}

	//名称
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	//性别
	private boolean sex;
	public boolean isSex() {
		return sex;
	}
	public void setSex(boolean sex) {
		this.sex = sex;
	}
}

清单二:Bird和Pig类,加入主要的属性,并继承Animal类。

package com.src.hibernate;
public class Bird extends Animal {

	//高度
	private int height;
	public int getHeight() {
		return height;
	}
	public void setHeight(int height) {
		this.height = height;
	}

}

package com.src.hibernate;
public class Pig extends Animal {

	//重量
	private int weight;
	public int getWeight() {
		return weight;
	}
	public void setWeight(int weight) {
		this.weight = weight;
	}
}

1.2、映射文件

映射文件里须要加入相应的映射,该模型中仅仅须要加入一个映射文件,由于仅仅生成一张表,在映射文件里加入相应的子类映射,使用<subclass>标签,标签中加入鉴别器discriminator-value,该鉴别器属性指明了在数据库中写入数据时指示写入的是何种类型,例如以下:

<?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.src.hibernate.Animal" table="t_animal">
		<id name="id">
			<generator class="native"/>
		</id>
		<!-- 增加鉴别标签,且必须放在id后面 -->
		<discriminator column="type" />
		<property name="name"/>
		<property name="sex" type="boolean"/>

		<subclass name="com.src.hibernate.Pig" discriminator-value="P">
			<property name="weight"/>
		</subclass>
		<subclass name="com.src.hibernate.Bird" discriminator-value="B">
			<property name="height"/>
		</subclass>
	</class>

</hibernate-mapping>

1.3、分析结果

生成的mysql数据库表中不仅会加入Animal的基本属性,并且会加入Pig和Bird的属性,由于在映射文件里使用<subclass>写出了所加入的属性,另外还加入了相应的鉴别器属性,所以在数据库中会加入相应的鉴别列,生成的表结构例如以下图:

二、数据操作

2.1 写入数据

在进行数据读取和写入操作时须要注意类中的操作使用了

public void testSave(){
	Session session=null;
	try{
		//创建session对象
		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("xiaoniaoniao");
		bird.setSex(true);
		bird.setHeight(100);
		session.save(bird);

		session.getTransaction().commit();
	}catch(Exception e){
		e.printStackTrace();
		session.getTransaction().rollback();
	}finally{
		HibernateUtils.closeSession(session);
	}

}

2.2  多态查询--get和hql

前几篇文章已经讨论了主要的查询方法,仅仅须要使用load和get方法就可以,这里重点讨论多态查询。多态查询是指Hibernate在载入对象时可以採用instanceof鉴别出其真正的类型的对象就可以为多态查询。

 Note:多态查询不支持延迟载入,也就是说假设使用load方法,须要在映射文件里将延迟载入设置为false。

2.2.1 load延迟载入

load支持延迟载入,在载入对象时事实上生成的是对象的代理,所以在使用多态查询时须要在映射文件里将延迟载入设置为false,例如以下:

<?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.src.hibernate.Animal" table="t_animal" lazy="false">
		<id name="id">
			<generator class="native"/>
		</id>
		<!-- 增加鉴别标签,且必须放在id后面 -->
		<discriminator column="type" />
		<property name="name"/>
		<property name="sex" type="boolean"/>

		<subclass name="com.src.hibernate.Pig" discriminator-value="P">
			<property name="weight"/>
		</subclass>
		<subclass name="com.src.hibernate.Bird" discriminator-value="B">
			<property name="height"/>
		</subclass>
	</class>
</hibernate-mapping>

load载入方法,使用load载入该演示样例中支持多态查询,在配置文件里将延迟载入设置为false,所以这里使用load方法可以载入获得对应的对象类。

public void testLoad(){
	Session session=null;
	try{
		session=HibernateUtils.getSession();
		session.beginTransaction();

		Animal ani=(Animal)session.load(Animal.class,1);
		System.out.println(ani.getName());
		//由于load默认支持lazy,所以我们看到的是Animal的代理
		//所以採用了instanceof无法鉴别出真正的类型Pig
		//所以load在此情况下是不支持多态查询的
		if(ani instanceof Pig){
			System.out.println("我是小猪猪!");
		}else{
			System.out.println("我不是小猪猪!");
		}
		session.getTransaction().commit();
	}catch(Exception e){
		e.printStackTrace();
		session.getTransaction().rollback();
	}finally{
		HibernateUtils.closeSession(session);
	}
}

2.2.2 hql查询

hql支持多态查询,这主要因为查询出的是一个真正的对象,并不会返回一个代理,所以hql支持多态查询,另外在查询时须要注意查询语句中不要使用表名,而是要使用类名称,Hibernate会依据类名称将其映射为相应的表名称,例如以下:

public void testLoad5(){
	Session session=null;
	try{
		session=HibernateUtils.getSession();
		session.beginTransaction();

		List<Animal> list=session.createQuery("from Animal").list();
		for(Iterator iter=list.iterator();iter.hasNext();){
			Animal a=(Animal)iter.next();
			if(a instanceof Pig){
				System.out.println("我是小猪猪!");
			}else{
				System.out.println("我不是小猪猪!");
			}
		}
		session.getTransaction().commit();
	}catch(Exception e){
		e.printStackTrace();
		session.getTransaction().rollback();
	}finally{
		HibernateUtils.closeSession(session);
	}
}

查询结果:

Hibernate: select animal0_.id as id0_, animal0_.name as name0_, animal0_.sex as sex0_, animal0_.weight as weight0_, animal0_.height as height0_, animal0_.type as type0_ from t_animal animal0_
我是小猪猪!
我不是小猪猪!
我是小猪猪!
我不是小猪猪!

结语

继承映射是对象模型中重要的关系映射,通过使用继承映射可以将继承关系转换为相应的关系表,在配置映射文件时须要使用<subclass>标签,另外还须要在标签中加入鉴别器属性来标明不同的类型,在操作读取时才干非常快的鉴别出相应的类型。

【Hibernate步步为营】--继承映射具体解释

时间: 2025-01-02 10:55:16

【Hibernate步步为营】--继承映射具体解释的相关文章

hibernate之继承映射

面向对象中有继承的概念,而关系型数据库却没有表与表之间的继承关系.解决思路有三种: 1.  继承关系层次一个表: 含义:使用一个表保存同一继承层次中的所有类,加额外字段来表示所属子类. 优点:多态查询,查询父类和所有子类数据时只需一次简单的查询,性能最佳: 缺点:在数据库表里添加各个区分子类的字段. 适用:需要多态查询,且子类的属性较少. 2.  每个具体类一个表: 含义:父类抽象化不对应一个表,每个子类对应一个表(每个子表包括父和子所有字段). 优点:实现的继承映射最简单. 缺点:多态查询持久

Hibernate的继承映射

何为继承映射: 继承映射:对于面向对象的程序设计语言而言,继承和多态是两个最基本的概念.Hibernate 的继承映射可以理解持久化类之间的继承关系.例如:人和学生之间的关系.学生继承了人,可以认为学生是一个特殊的人,如果对人进行查询,学生的实例也将被得到. 继承映射的分类:Hibernate支持三种继承映射策略: 使用 subclass 进行映射:将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态.(数据看起来会很模糊,因为子类和父类的数据

hibernate笔记--继承映射关系的三种实现方式

单表继承映射(一张表): 假设我们现在有三个类,关系如下: Person类有两个子类Student和Teacher,并且子类都具有自己独有的属性.这种实体关系在hibernate中可以使用单表的继承映射来建表,最后生成的表是这样的: 可以看到我们只需要建立一张表就可以维护这个关系,这种方式就是单表继承映射,下面介绍配置方法: 新建实体类Person ,Student,和Teacher : public class Person { private int id; private String n

Hibernate配置文件和映射元素解释

象关系的映射是用一个XML文档来说明的.映射文档可以使用工具来生成,如XDoclet,Middlegen和AndroMDA等.下面从一个映射的例子开始讲解映射元素. AD:干货来了,不要等!WOT2015 北京站演讲PPT开放下载! <!--标准的XML文件的起始行,version='1.0'表明XML的版本,encoding='gb2312'表明XML文件的编码方式--> <?xml version='1.0' encoding='gb2312'?> <!--表明解析本XM

hibernate中继承映射保存

1 简单继承映射,在子类上进行映射配置,可以将父类属性直接配置在子类映射文件中. 简单例子如下:teacher类继承自Person类. public class Person { private int id; private String pname; public Person() { // TODO Auto-generated constructor stub } public int getId() { return id; } public void setId(int id) {

hibernate 继承映射

对于面向对象的程序设计语言而言,继承和多态是两个最基本的概念.Hibernate 的继承映射可以理解持久化类之间的继承关系.例如:人和学生之间的关系.学生继承了人,可以认为学生是一个特殊的人,如果对人进行查询,学生的实例也将被得到. Hibernate支持三种继承映射策略: 使用 subclass 进行映射:将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态. 使用 joined-subclass 进行映射: 对于继承关系中的子类使用同一个表

【SSH快速进阶】——Hibernate继承映射:每棵继承树映射一张表

我们都知道,Hibernate最大的一个优点就是使开发更加"面向对象",类与类之间有继承关系,Hibernate中也对这种继承关系提供了映射的封装. Hibernate为继承映射提供了三种策略 1.每棵继承树使用一张表 2.每个子类使用一张表 3.每个具体类使用一张表 本文对第一种策略进行说明. 场景 如下类图 上图中Pig类和Bird类继承Animal类,每棵继承树对应一张表,即在同一棵继承树中,所有的类的对象信息(记录)共同存放到一张表中,要判断某条记录属于哪个对象,需要在表中添加

Hibernate4.x之映射关系--继承映射

Hibernate的继承映射可以理解为持久化类之间的继承关系.例如:人和学生之间的关系.学生继承了人,可以认为学生是一个特殊的人,如果对人进行查询,学生的实例也将被得到. Hibernate支持以下三种继承映射策略: 使用subclass进行映射:将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态 使用joined-subclass进行映射:对于继承关系中的子类使用同一个表,这就需要在数据库表汇总增加额外的区分子类类型的字段 使用union-

【Hibernate步步为营】--继承映射详解

上篇文章讨论了多对多映射,在使用多对多映射时重点是使用<many-to-many>标签,并在标签的两端加入外键这样在生成关系时会创建两个关系之间的关系表,通过关系表来维护它们之间的关系,另外对于单向和双向的区别是在映射的哪一端添加标签的问题.在面向对象中很重要的一个特性就是继承,继承实现了代码的复用,而且Hibernate把基本上所有的对象模型进行了映射封装,其中就包括继承映射,接下来就详细讨论. 一.继承映射 继承是面向对象很重要的特性,它实现了代码的服用,在关系模型中同样也有继承关系,这种