上篇文章讨论了多对多映射,在使用多对多映射时重点是使用<many-to-many>标签,并在标签的两端加入外键这样在生成关系时会创建两个关系之间的关系表,通过关系表来维护它们之间的关系,另外对于单向和双向的差别是在映射的哪一端加入标签的问题。在面向对象中非常重要的一个特性就是继承,继承实现了代码的复用,并且Hibernate把基本上全部的对象模型进行了映射封装,当中就包含继承映射,接下来就具体讨论。
继承是面向对象非常重要的特性,它实现了代码的服用,在关系模型中相同也有继承关系,这样的继承关系事实上能够看做是一种枚举关系,一种类型中能够枚举出非常多子类型,这些子类型和父对象形成了继承关系,能够对其进行枚举的大部分都能够看做是一种继承映射,所以这样的枚举关系能够看做是继承映射,比如动物就是一种抽象类,它是其他动物猪、猫等的父类,它们之间就是一种继承关系,例如以下图:
 
      
这样的继承映射在转化为关系模型后会生成一张表,那么这张表是怎样区分这两种类型的呢?用的是关系字段,须要在表中加入类型字段,使用keyword来标明对象的类型。所以上图中的对象模型相应的表结构例如以下:
清单一: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;
	}
}
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;
	}
}
<?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>
生成的mysql数据库表中不仅会加入Animal的基本属性,并且会加入Pig和Bird的属性,由于在映射文件里使用<subclass>写出了所加入的属性,另外还加入了相应的鉴别器属性,所以在数据库中会加入相应的鉴别列,生成的表结构例如以下图:
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);
	}
}
<?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>
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);
	}
}
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步步为营】--继承映射具体解释,布布扣,bubuko.com
原文:http://www.cnblogs.com/mfrbuaa/p/3809607.html