(14)Hibernate继承映射

人们总是在失去时,才了解到事情的本质

需求:动物、猫、猴子

1、简单继承映射

Animal.java

package com.rk.hibernate.n_inheritance1;

public abstract class Animal
{
	private int id;
	private String name;
	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;
	}

}

Cat.java

package com.rk.hibernate.n_inheritance1;

public class Cat extends Animal
{
	private String catchMouse;

	public String getCatchMouse()
	{
		return catchMouse;
	}

	public void setCatchMouse(String catchMouse)
	{
		this.catchMouse = catchMouse;
	}

	@Override
	public String toString()
	{
		return "Cat [id=" + getId() + ", name=" + getName() + ", catchMouse=" + catchMouse + "]";
	}

}

Cat.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.rk.hibernate.n_inheritance1" auto-import="true">
	<class name="Cat" table="T_Cat">
		<!-- 简单继承映射: 父类属性直接写 -->
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		<property name="name" column="name"></property>
		<property name="catchMouse" column="catchMouse"></property>
	</class>
</hibernate-mapping>

App.java

package com.rk.hibernate.n_inheritance1;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App
{
	private static SessionFactory sf;
	static
	{
		sf = new Configuration()
						.configure()
						.addClass(Cat.class)
						.buildSessionFactory();
	}

	@Test
	public void testSave()
	{
		Session session = sf.openSession();
		session.beginTransaction();

		//猫
		Cat cat = new Cat();
		cat.setName("大花猫");
		cat.setCatchMouse("抓小老鼠");

		//保存
		session.save(cat);

		session.getTransaction().commit();
		session.close();
	}

	@Test
	public void testGetCat()
	{
		Session session = sf.openSession();
		session.beginTransaction();

		//通过HQL查询Cat
		Query q = session.createQuery("from Cat");
		List<Cat> list = q.list();

		System.out.println(list);

		session.getTransaction().commit();
		session.close();
	}

	@Test
	public void testGetAnimal()
	{
		Session session = sf.openSession();
		session.beginTransaction();

		// 获取时候注意:当写hql查询的使用,通过父类查询必须写上类的全名
		Query q = session.createQuery("from com.rk.hibernate.n_inheritance1.Animal");
		List<Cat> list = q.list();

		System.out.println(list);

		session.getTransaction().commit();
		session.close();
	}
}

生成的T_Cat表

总结:简单继承映射,有多少个子类,写多少个映射文件!

2、继承映射

下面3种方法都是只使用一个映射文件(Animal.hbm.xml文件),但是不同的方法生成的数据库表的数量不同。

2.1、所有子类映射到同一张表(1张表)

什么情况用?

子类教多,且子类较为简单,即只有个别属性!

好处:因为使用一个映射文件, 减少了映射文件的个数。

缺点:(不符合数据库设计原则)

Animal.java

package com.rk.hibernate.n_inheritance2;

public abstract class Animal
{
	private int id;
	private String name;
	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;
	}

}

Cat.java

package com.rk.hibernate.n_inheritance2;

public class Cat extends Animal
{
	private String catchMouse;

	public String getCatchMouse()
	{
		return catchMouse;
	}

	public void setCatchMouse(String catchMouse)
	{
		this.catchMouse = catchMouse;
	}

	@Override
	public String toString()
	{
		return "Cat [id=" + getId() + ", name=" + getName() + ", catchMouse=" + catchMouse + "]";
	}

}

Monkey.java

package com.rk.hibernate.n_inheritance2;

public class Monkey extends Animal
{
	private String eatBanana;

	public String getEatBanana()
	{
		return eatBanana;
	}

	public void setEatBanana(String eatBanana)
	{
		this.eatBanana = eatBanana;
	}

}

Animal.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<!-- 
	继承映射, 所有的子类都映射到一张表
 -->
<hibernate-mapping package="com.rk.hibernate.n_inheritance2" auto-import="true">
	<class name="Animal" table="T_Animals">
		<!-- 简单继承映射: 父类属性直接写 -->
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		<!-- 指定鉴别器字段(区分不同的子类) -->
		<discriminator column="animal_Type"></discriminator>

		<property name="name" column="name"></property>

		<!-- 
			子类:猫
				每个子类都用subclass节点映射
				注意:一定要指定鉴别器字段,否则报错!
				鉴别器字段:作用是在数据库中区别每一个子类的信息, 就是一个列(column)
			discriminator-value="cat"
				指定鉴别器字段,即animal_Type字段的值
				如果不指定,默认为当前子类的全名
		 -->
		<subclass name="Cat" discriminator-value="cat">
			<property name="catchMouse" column="catchMouse"></property>
		</subclass>

		 <!-- 
		 	子类:猴子
		  -->
		<subclass name="Monkey" discriminator-value="monkey">
			<property name="eatBanana" column="eatBanana"></property>
		</subclass>
	</class>
</hibernate-mapping>

App.java

package com.rk.hibernate.n_inheritance2;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App
{
	private static SessionFactory sf;
	static
	{
		sf = new Configuration()
						.configure()
						.addClass(Animal.class)
						.buildSessionFactory();
	}

	@Test
	public void testSave()
	{
		Session session = sf.openSession();
		session.beginTransaction();

		//猫
		Cat cat = new Cat();
		cat.setName("大花猫");
		cat.setCatchMouse("抓小老鼠");

		//猴子
		Monkey monkey = new Monkey();
		monkey.setName("淘气猴");
		monkey.setEatBanana("吃黄香蕉");

		//保存
		session.save(cat);
		session.save(monkey);

		session.getTransaction().commit();
		session.close();
	}

}

生成的T_Animals表

总结:写法较为简单:所有子类用一个映射文件,且映射到一张表!但数据库设计不合理!不推荐用。

2.2、每个类映射一张表(3张表)

Animal.java

package com.rk.hibernate.n_inheritance3;

public abstract class Animal
{
	private int id;
	private String name;
	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;
	}

}

Cat.java

package com.rk.hibernate.n_inheritance3;

public class Cat extends Animal
{
	private String catchMouse;

	public String getCatchMouse()
	{
		return catchMouse;
	}

	public void setCatchMouse(String catchMouse)
	{
		this.catchMouse = catchMouse;
	}

	@Override
	public String toString()
	{
		return "Cat [id=" + getId() + ", name=" + getName() + ", catchMouse=" + catchMouse + "]";
	}

}

Monkey.java

package com.rk.hibernate.n_inheritance3;

public class Monkey extends Animal
{
	private String eatBanana;

	public String getEatBanana()
	{
		return eatBanana;
	}

	public void setEatBanana(String eatBanana)
	{
		this.eatBanana = eatBanana;
	}

}

Animal.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<!-- 
	继承映射, 每个类对应一张表(父类也对应表)
 -->
<hibernate-mapping package="com.rk.hibernate.n_inheritance3" auto-import="true">
	<class name="Animal" table="T_Animal_Each">
		<id name="id" column="id">
			<generator class="native"></generator>
		</id>
		<property name="name" column="name"></property>

		<!-- 
			子类:猫  t_cat
			key 指定_cat表的外键字段
		-->
		<joined-subclass name="Cat" table="T_Cat_Each">
			<key column="animal_Id"></key>
			<property name="catchMouse" column="catchMouse"></property>
		</joined-subclass>

		<!-- 子类:猴子  t_monkey -->
		<joined-subclass name="Monkey" table="T_Monkey_Each">
			<key column="animal_Id"></key>
			<property name="eatBanana" column="eatBanana"></property>
		</joined-subclass>
	</class>
</hibernate-mapping>
	

App.java

package com.rk.hibernate.n_inheritance3;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App
{
	private static SessionFactory sf;
	static
	{
		sf = new Configuration()
						.configure()
						.addClass(Animal.class)
						.buildSessionFactory();
	}

	@Test
	public void testSave()
	{
		Session session = sf.openSession();
		session.beginTransaction();

		//猫
		Cat cat = new Cat();
		cat.setName("大花猫");
		cat.setCatchMouse("抓小老鼠");

		//猴子
		Monkey monkey = new Monkey();
		monkey.setName("淘气猴");
		monkey.setEatBanana("吃黄香蕉");

		//保存
		session.save(cat);
		session.save(monkey);

		session.getTransaction().commit();
		session.close();
	}

}

生成的T_Animal_Each表

生成的T_Cat_Each表

生成的T_Monkey_Each表

总结:一个映射文件,存储所有的子类; 子类父类都对应表; 缺点:表结构比较负责,插入一条子类信息,需要用2条sql: 往父类插入、往子类插入!

2.3、(推荐)每个子类映射一张表, 父类不对应表(2张表)

Animal.java

package com.rk.hibernate.n_inheritance4;

public abstract class Animal
{
	private String id;
	private String name;
	public String getId()
	{
		return id;
	}
	public void setId(String id)
	{
		this.id = id;
	}
	public String getName()
	{
		return name;
	}
	public void setName(String name)
	{
		this.name = name;
	}

}

Cat.java

package com.rk.hibernate.n_inheritance4;

public class Cat extends Animal
{
	private String catchMouse;

	public String getCatchMouse()
	{
		return catchMouse;
	}

	public void setCatchMouse(String catchMouse)
	{
		this.catchMouse = catchMouse;
	}

	@Override
	public String toString()
	{
		return "Cat [id=" + getId() + ", name=" + getName() + ", catchMouse=" + catchMouse + "]";
	}

}

Monkey.java

package com.rk.hibernate.n_inheritance4;

public class Monkey extends Animal
{
	private String eatBanana;

	public String getEatBanana()
	{
		return eatBanana;
	}

	public void setEatBanana(String eatBanana)
	{
		this.eatBanana = eatBanana;
	}

}

Animal.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<!-- 
	继承映射, 每个类对应一张表(父类不对应表)
 -->
<hibernate-mapping package="com.rk.hibernate.n_inheritance4" auto-import="true">
	<!-- 
		 abstract="true"  指定实体类对象不对应表,即在数据库内不生成表
	 -->
	<class name="Animal" table="T_Animal_Final">
		<!-- 如果用union-subclass节点,主键生成策略不能为自增长! -->
		<id name="id" column="id">
			<generator class="uuid"></generator>
		</id>
		<property name="name" column="name"></property>

		<!-- 
			子类:猫  
			union-subclass  
				table 指定为表名, 表的主键即为id列
		-->
		<union-subclass name="Cat" table="T_Cat_Final">
			<property name="catchMouse" column="catchMouse"></property>
		</union-subclass>

		<!-- 子类:猴子  -->
		<union-subclass name="Monkey" table="T_Monkey_Final">
			<property name="eatBanana" column="eatBanana"></property>
		</union-subclass>
	</class>
</hibernate-mapping>
	

App.java

package com.rk.hibernate.n_inheritance4;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App
{
	private static SessionFactory sf;
	static
	{
		sf = new Configuration()
						.configure()
						.addClass(Animal.class)
						.buildSessionFactory();
	}

	@Test
	public void testSave()
	{
		Session session = sf.openSession();
		session.beginTransaction();

		//猫
		Cat cat = new Cat();
		cat.setName("大花猫");
		cat.setCatchMouse("抓小老鼠");

		//猴子
		Monkey monkey = new Monkey();
		monkey.setName("淘气猴");
		monkey.setEatBanana("吃黄香蕉");

		//保存
		session.save(cat);
		session.save(monkey);

		session.getTransaction().commit();
		session.close();
	}

}

生成的T_Animal_Final表,虽然会生成这个表,但是不会存储数据

生成的T_Cat_Final表

生成的T_Monkey_Final表

总结:所有的子类都写到一个映射文件;父类不对应表; 每个子类对应一张表。
时间: 2024-10-16 11:52:30

(14)Hibernate继承映射的相关文章

【SSH快速进阶】——Hibernate继承映射:每个具体类映射一张表

上篇文章说的是每个类映射一张表,不管是父类还是子类.与上篇文章不同的是,这里是每个"具体类"映射一张表,什么意思呢?就是让每个子类(具体的.有意义的类)映射一张表. 场景 与上篇文章场景一样,如下类图 上图中Pig类和Bird类继承Animal类,要让每个具体类映射一张表,就是只映射Pig和Bird,如下表所示: (表 1) 上面的表有个特点就是,t_pig和t_bird的主键永远都不会相同.因为表面上看起来这是两张表,但实际上存储的都是动物(同一类型),所以还可以看做是一张表. 配置

hibernate 继承映射

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

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

上文说了每棵继承树映射一张表,本文继续描述让每个类都映射一张表的配置. 场景 与上篇文章场景一样,如下类图 上图中Pig类和Bird类继承Animal类,要让每个类映射一张表,就是让着三个类都分别映射一张表,但同时这三张表也跟对应的三个类似的,有继承关系,如下表所示: (表 1) Pig和Bird的记录都表示一个动物,因此都会在Animal对应的表中存储,而它们各自的拓展属性则存储在各自对应的表中,主键与Animal对应记录的主键各自对应. 配置 PO对象 跟上篇文章一样,实体类没有任何变化.

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

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

SSH开发实践part3:hibernate继承映射

0 大家好.上次讲了关于hibernate中双向1-N的映射配置,可以参考:http://www.cnblogs.com/souvenir/p/3784510.html 实际项目中,对象间的关系比较复杂,除了上次讲的相互关联以外,这次我们要讲的就是关于对象的继承.hibernate如何来通过配置完成对象的继承? 1 比如有一个父类person,然后两个对应的子类,一个是teacher,一个是student.教师和老师除了拥有person这个类所有的属性以外,还会有一些自己独特的属性. hiber

JPA Hibernate 继承映射

在面向对象的程序领域中,类与类之间是有继承关系的,例如Java世界中只需要extends关键字就可以确定这两个类的父子关系,但是在关系数据库中,有的知识关联关系.为了将继承映射到关系数据库中,Hibernate提供了3中方式 整个的继承体系就用一张表(single_table)注解:@Inheritance(strategy =InheritanceType.SINGLE_TABLE) 每个类一张表,子类存放所特有的属.性注解:@Inheritance(strategy= Inheritance

Hibernate继承映射

在面向对象的程序领域中,类与类之间是有继承关系的,例如Java世界中只需要extends关键字就可以确定这两个类的父子关系,但是在关系数据库的世 界中,表与表之间没有任何关键字可以明确指明这两张表的父子关系,表与表是没有继承关系这样的说法的.为了将程序领域中的继承关系反映到数据 中,Hibernate为我们提供了3中方案: 第一种方案:一个子类对应一张表. 第二种方案:使用一张表表示所有继承体系下的类的属性的并集. 第三种方案:每个子类使用一张表只存储它特有的属性,然后与父类所对应的表以一对一主

hibernate 继承映射(一)

每棵继承树映射成一张表 测试代码: public void testSave1() {         Session session = null;         try {             session = HibernateUtils.getSession();             session.beginTransaction();                          Pig pig = new Pig();             pig.setName

hibernate 继承映射(二)

每个子类映射成一张表: 每个具体类映射成一张表: