1. Hibernate支持三种继承映射策略:
–使用 subclass进行映射:将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态。
–使用 joined-subclass进行映射:对于继承关系中的子类使用同一个表,这就需要在数据库表中增加额外的区分子类类型的字段。
–使用 union-subclass
进行映射:域模型中的每个类映射到一个表,通过关系数据模型中的外键来描述表之间的继承关系。这也就相当于按照域模型的结构来建立数据库中的表,并通过外键来建立表之间的继承关系。

2.  采用subclass元素的继承映射:

•采用 subclass的继承映射可以实现对于继承关系中父类和子类使用同一张表
•因为父类和子类的实例全部保存在同一个表中,因此需要在该表内增加一列,使用该列来区分每行记录到低是哪个类的实例----这个列被称为辨别者列(discriminator).
•在这种映射策略下,使用 subclass来映射子类,使用class
或 subclass的
discriminator-value属性指定辨别者列的值
•所有子类定义的字段都不能有非空约束。如果为那些字段添加非空约束,那么父类的实例在那些列其实并没有值,这将引起数据库完整性冲突,导致父类的实例无法保存到数据库中

代码示例:

Person类

public class Person {

	private int id;
private String name;
private int age;
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 int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
} }

继承了Person类的Student类:

public class Student extends Person {
private String school; public String getSchool() {
return school;
} public void setSchool(String school) {
this.school = school;
} }

Person类对应的hbm配置文件

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2015-10-26 22:01:46 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.elgin.hibernate.subclass">
<class name="Person" table="PERSON" discriminator-value="person">
<id name="id" type="int">
<column name="ID" />
<generator class="native" />
</id>
<!-- 配置辨别者列 -->
<discriminator column="TYPE" type="java.lang.String">
</discriminator> <property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="age" type="int">
<column name="AGE" />
</property>
<!-- 映射student子类 -->
<subclass name="Student" discriminator-value="student">
<property name="school" column="SCHOOL" type="java.lang.String"></property>
</subclass>
</class>
</hibernate-mapping>

单元测试类:

public class HibernateTest {

	//如此声明只为方便测试,生产环境不能这么用
private SessionFactory sessionFactory;
private Session session;
private Transaction transcation; @Before
public void init(){
Configuration cfg=new Configuration().configure();
ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
sessionFactory=cfg.buildSessionFactory(serviceRegistry);
session=sessionFactory.openSession();
transcation=session.beginTransaction();
}
/*
* subclass继承映射缺点
* 1.加入了辨别者列
* 2.子类独有的字段不能添加非空约束
* 3.若继承层次较深,则数据表的字段也会较多
*
*/ /**
* 插入操作:
* 1.对于子类,只需把数据插入到一张表中
* 2.辨别者列由hibernate自动维护
*
*/
@Test
public void testSave(){
Person person=new Person();
person.setName("peter");
person.setAge(20); Student student=new Student();
student.setAge(22);
student.setName("phne");
student.setSchool("beida"); session.save(person);
session.save(student);
} /**
* 1.查询父类记录只需要查询一张数据表,结果包含子类数据
* 2.查询子类记录同样之查询一张数据表,结果只有子类
*/
@SuppressWarnings("unchecked")
@Test
public void testquery(){
List<Person> persons=session.createQuery("from Person").list();
System.out.println(persons.size()); List<Student> stus=session.createQuery("from Student").list();
System.out.println(stus.size());
} @After
public void destory(){
transcation.commit();
session.close();
sessionFactory.close();
} }

3.  采用 joined-subclass元素的继承映射

•采用joined-subclass元素的继承映射可以实现每个子类一张表
•采用这种映射策略时,父类实例保存在父类表中,子类实例由父类表和子类表共同存储。因为子类实例也是一个特殊的父类实例,因此必然也包含了父类实例的属性。于是将子类和父类共有的属性保存在父类表中,子类增加的属性,则保存在子类表中。
•在这种映射策略下,无须使用鉴别者列,但需要为每个子类使用 key元素映射共有主键。
•子类增加的属性可以添加非空约束。因为子类的属性和父类的属性没有保存在同一个表中

代码示例:

Person类和Student类同上

Person类对应的hbm配置文件:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2015-10-26 22:01:46 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.elgin.hibernate.joined_subclass">
<class name="Person" table="PERSON" discriminator-value="person">
<id name="id" type="int">
<column name="ID" />
<generator class="native" />
</id> <property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="age" type="int">
<column name="AGE" />
</property>
<!-- 映射student子类 -->
<joined-subclass name="Student" table="STUDENTS">
<key column="PERSON_ID"></key>
<property name="school" column="SCHOOL" type="java.lang.String"></property>
</joined-subclass>
</class>
</hibernate-mapping>

单元测试类:

public class HibernateTest {

	//如此声明只为方便测试,生产环境不能这么用
private SessionFactory sessionFactory;
private Session session;
private Transaction transcation; @Before
public void init(){
Configuration cfg=new Configuration().configure();
ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
sessionFactory=cfg.buildSessionFactory(serviceRegistry);
session=sessionFactory.openSession();
transcation=session.beginTransaction();
}
/*
* joined-subclass继承映射优点:
* 1.无需要加入辨别者列
* 2.子类独有的字段能添加非空约束
* 3.没有冗余的字段
*
*/ /**
* 插入操作:
* 1.对于子类记录至少插入2张数据表
*
*/
@Test
public void testSave(){
Person person=new Person();
person.setName("peter");
person.setAge(20); Student student=new Student();
student.setAge(22);
student.setName("phne");
student.setSchool("beida"); session.save(person);
session.save(student);
} /**
* 1.查询父类记录,做左外连接查询2张表
* 2.查询子类记录,做内连接查询2张表
*/
@SuppressWarnings("unchecked")
@Test
public void testquery(){
List<Person> persons=session.createQuery("from Person").list();
System.out.println(persons.size()); List<Student> stus=session.createQuery("from Student").list();
System.out.println(stus.size());
} @After
public void destory(){
transcation.commit();
session.close();
sessionFactory.close();
} }

4.  采用 union-subclass元素的继承映射

•采用 union-subclass元素可以实现将每一个实体对象映射到一个独立的表中。
•子类增加的属性可以有非空约束---即父类实例的数据保存在父表中,而子类实例的数据保存在子类表中。
•子类实例的数据仅保存在子类表中,而在父类表中没有任何记录
•在这种映射策略下,子类表的字段会比父类表的映射字段要多,因为子类表的字段等于父类表的字段、加子类增加属性的总和
•在这种映射策略下,既不需要使用鉴别者列,也无须使用key元素来映射共有主键.
•使用 union-subclass映射策略是不可使用identity的主键生成策略, 因为同一类继承层次中所有实体类都需要使用同一个主键种子,即多个持久化实体对应的记录的主键应该是连续的.受此影响,也不该使用native主键生成策略,因为native会根据数据库来选择使用identity或sequence.
  示例代码:
同样,Person类和Student类同上
Person类对应的hbm映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2015-10-26 22:01:46 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping package="com.elgin.hibernate.union_subclass">
<class name="Person" table="PERSON" discriminator-value="person">
<id name="id" type="int">
<column name="ID" />
<generator class="hilo" />
</id> <property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="age" type="int">
<column name="AGE" />
</property>
<!-- 映射student子类 -->
<union-subclass name="Student" table="STUDENT">
<property name="school" column="SCHOOL" type="java.lang.String"></property>
</union-subclass>
</class>
</hibernate-mapping>

单元测试类:

public class HibernateTest {

	//如此声明只为方便测试,生产环境不能这么用
private SessionFactory sessionFactory;
private Session session;
private Transaction transcation; @Before
public void init(){
Configuration cfg=new Configuration().configure();
ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(cfg.getProperties()).buildServiceRegistry();
sessionFactory=cfg.buildSessionFactory(serviceRegistry);
session=sessionFactory.openSession();
transcation=session.beginTransaction();
}
/*
* union-subclass继承映射优点:
* 1.无需要加入辨别者列
* 2.子类独有的字段能添加非空约束
*
* 缺点:
* 1.存在冗余字段
* 2.若更新父类表字段,更新效率低
*/ /**
* 插入操作:
*
*/
@Test
public void testSave(){
Person person=new Person();
person.setName("peter");
person.setAge(20); Student student=new Student();
student.setAge(22);
student.setName("phone");
student.setSchool("北大"); session.save(person);
session.save(student);
} /**
* 1.查询父类记录,需要把父类记录和子类记录汇总到一起再做查询,性能稍差
* 2.查询子类记录,只要查子类记录表即可
*/
@SuppressWarnings("unchecked")
@Test
public void testquery(){
List<Person> persons=session.createQuery("from Person").list();
System.out.println(persons.size()); List<Student> stus=session.createQuery("from Student").list();
System.out.println(stus.size());
} @Test
public void testUpdate(){
String hql="update Person p set p.age=45";
session.createQuery(hql).executeUpdate();
} @After
public void destory(){
transcation.commit();
session.close();
sessionFactory.close();
} }

5.  3种继承映射方式的对比图






最新文章

  1. 在Ubuntu中建立MySQL数据库
  2. web前端性能优化指南(转)
  3. django个人总结
  4. NetFPGA
  5. Linux下I/O模型
  6. 关于n!mod p
  7. react-native Unrecognized font family ‘Lonicons’;
  8. Spring如何处理线程并发
  9. HW1.5
  10. jsp servelet
  11. redis实现spring-data-redis整合
  12. 转的git
  13. javascript学习笔记(1) 简单html语法
  14. cocos2dx中Action汇总
  15. 顶级jQuery树插件
  16. Excel和notepad++加之更换
  17. [LeetCode] Super Washing Machines 超级洗衣机
  18. JAVA WEB快速入门之环境搭建
  19. rank() partition by 排名次
  20. c语言计算过程中的过程转换

热门文章

  1. 数组 寻找最大的第k个数
  2. asp.net TreeView与XML配合使用v1.1
  3. 在CentOS 6.X 上面安装 Python 2.7.X
  4. apk反编译(6)ProGuard 工具 android studio版官方教程[作用,配置,解混淆,优化示例]
  5. [Codeforces673C]Bear and Colors(枚举,暴力)
  6. 全球最受欢迎的十大Linux发行版(图)
  7. Windows SDK 实现不规则窗口介绍
  8. 完全二叉树的高度为什么是对lgN向下取整
  9. BZOJ 1861 书架
  10. busybox filesystem add ldd function