• 背景:

  在一些项目中,会采用集成的关系来定义数据库实体类,比如:人(Person)与学生(Student),学生来源与人,所以人的基本属性学生也拥有;但学生有的一些属性,人就不具有。人与学生之间很显然就拥有了继承关系------学生继承于人,人是父类,学生是子类。

  那么,这种继承关系在hibernate是如何映射呢?

  对于面向对象的程序设计语言而言,继承和多态是两个最基本的概念。hibernate的集成映射可以理解为持久化类之间的继承关系。在上边的例子中,学生集成了人,可以认为学生是一个特殊的人,如果对人进行查询,学生的实例也将被得到。

  在hibernate中支持三种继承映射策略:

  1)使用subclass进行映射:将域模型中的每一个实体对象映射到一个独立的表中,也就是说不用在关系数据模型中考虑域模型中的继承关系和多态。

  2)使用jioned-subclass进行映射:对于继承关系中的子类使用同一个表,这就需要在数据库表中增加额外的区分子类类型的字段。

  3)使用union-subclass进行映射:域模型中的每个类映射到一个表,通过关系数据模型中的外键来描述表之间的继承关系。这也就相当于按照域模型的结构来建立数据库中的表,并通过外键来建立表之间的继承关系。

  • 使用subclass进行映射

新建工程Hibernate08,导入hibernate开发包及mysql驱动包。

在src下新建hibernate.cfg.xml配置文件:

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">123456</property>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_01</property> <!-- <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.format_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="hibernate.current_session_context_class">thread</property> <property name="hibernate.c3p0.max_size">500</property>
<property name="hibernate.c3p0.min_size">20</property>
<property name="hibernate.c3p0.max_statements">10</property>
<property name="hibernate.c3p0.timeout">2000</property>
<property name="hibernate.c3p0.idle_test_period">2000</property>
<property name="hibernate.c3p0.acquire_increment">10</property> <mapping resource="com/dx/hibernate06/extend/Person.hbm.xml" /> </session-factory>
</hibernate-configuration>

在src下新建com.dx.hibernate06.extend包,在该包下新建Person.java:

 package com.dx.hibernate06.extend;

 public class Person {
private Integer id;
private String name;
private Integer age; public Person() { } public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
}
}

新建Student.java(继承自Person):

 package com.dx.hibernate06.extend;

 public class Student extends Person {
private String className;
private String schoolName; public Student() { } public String getClassName() {
return className;
} public void setClassName(String className) {
this.className = className;
} public String getSchoolName() {
return schoolName;
} public void setSchoolName(String schoolName) {
this.schoolName = schoolName;
} }

添加Person.hbm.xml配置文件:

 <?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 2017-6-8 15:16:00 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="com.dx.hibernate06.extend">
<class name="Person" table="PERSONS" discriminator-value="person">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id> <!-- 配置辨别者列 -->
<discriminator column="TYPE" type="string"></discriminator> <property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="age" type="java.lang.Integer">
<column name="AGE" />
</property> <subclass name="Student" discriminator-value="student">
<property name="className" column="CLASS_NAME" type="string"></property>
<property name="schoolName" column="SCHOOL_NAME" type="string"></property>
</subclass>
</class>
</hibernate-mapping>

注意:

1)在这里并没有定义student.hbm.xml配置文件,而是只需要在Person.hbm.xml配置文件中设置subclass配置项就可以;

2)除了设置subclass节点,还需要添加discriminator(辨别列)节点配置,且需要在table和subclass节点中设置discriminator-value(辨别列值)。

添加测试类TestMain.java:

 package com.dx.hibernate06.extend;

 import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; public class TestMain {
private SessionFactory sessionFactory = null;
private Session session = null;
private Transaction transaction = null; @Before
public void init() {
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().configure().build();
Metadata metadata = new MetadataSources(standardRegistry).getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyComponentPathImpl.INSTANCE).build(); sessionFactory = metadata.getSessionFactoryBuilder().build();
session = sessionFactory.getCurrentSession();
transaction = session.beginTransaction();
} @After
public void destory() {
transaction.commit();
session.close();
sessionFactory.close();
}
}

测试:

在TestMain.java中添加测试函数1:

     @Test
public void testInsert() {
Person person = new Person();
person.setName("person1");
person.setAge(27); Student student = new Student();
student.setName("student1");
student.setAge(22);
student.setClassName("class-1");
student.setSchoolName("浙江大学"); session.save(person);
session.save(student);
}

测试执行sql:

 Hibernate: 

     create table PERSONS (
ID integer not null auto_increment,
TYPE varchar(255) not null,
NAME varchar(255),
AGE integer,
CLASS_NAME varchar(255),
SCHOOL_NAME varchar(255),
primary key (ID)
) engine=InnoDB
Hibernate:
insert
into
PERSONS
(NAME, AGE, TYPE)
values
(?, ?, 'person')
Hibernate:
insert
into
PERSONS
(NAME, AGE, CLASS_NAME, SCHOOL_NAME, TYPE)
values
(?, ?, ?, ?, 'student')

数据库查寻结果:

添加测试函数2:

    @Test
public void testSelect() {
List<Person> persons = session.createQuery("FROM Person").list();
System.out.println(persons.size()); List<Student> students = session.createQuery("FROM Student").list();
System.out.println(students.size());
}

执行sql及结果:

 Hibernate:
select
person0_.ID as ID1_0_,
person0_.NAME as NAME3_0_,
person0_.AGE as AGE4_0_,
person0_.CLASS_NAME as CLASS_NA5_0_,
person0_.SCHOOL_NAME as SCHOOL_N6_0_,
person0_.TYPE as TYPE2_0_
from
PERSONS person0_
2
Hibernate:
select
student0_.ID as ID1_0_,
student0_.NAME as NAME3_0_,
student0_.AGE as AGE4_0_,
student0_.CLASS_NAME as CLASS_NA5_0_,
student0_.SCHOOL_NAME as SCHOOL_N6_0_
from
PERSONS student0_
where
student0_.TYPE='student'
1
  • 使用jioned-subclass进行映射

在工程中复制包com.dx.hibernate06.extend,并命名新包名称为:com.dx.hibernate06.joined.subclass

修改Person.hbm.xml:

 <?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 2017-6-8 15:16:00 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="com.dx.hibernate06.joined.subclass">
<class name="Person" table="PERSONS">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id> <property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="age" type="java.lang.Integer">
<column name="AGE" />
</property> <joined-subclass name="Student" table="STUDENTS">
<key>
<column name="STUDENT_ID"></column>
</key>
<property name="className" column="CLASS_NAME" type="string"></property>
<property name="schoolName" column="SCHOOL_NAME" type="string"></property>
</joined-subclass>
</class>
</hibernate-mapping>

注意:

1)这里不需要添加discriminator(辨别列)节点配置,也不需要在table和joined-subclass节点中设置discriminator-value(辨别列值);

2)但需要在joined-subclass节点中指定表名,及在节点内部指定key column。

修改hibernate.cfg.xml,修改mapping节点指定文件路径:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
。。。
<mapping resource="com/dx/hibernate06/joined/subclass/Person.hbm.xml" />
</session-factory>
</hibernate-configuration>

测试:

在com.dx.hibernate06.joined.subclass.TestMain.java中执行测试函数testInsert()(备注:该测试函数与上边测试函数一致),执行sql及结果:

 Hibernate: 

     create table PERSONS (
ID integer not null auto_increment,
NAME varchar(255),
AGE integer,
primary key (ID)
) engine=InnoDB
Hibernate: create table STUDENTS (
STUDENT_ID integer not null,
CLASS_NAME varchar(255),
SCHOOL_NAME varchar(255),
primary key (STUDENT_ID)
) engine=InnoDB
Hibernate: alter table STUDENTS
add constraint FK3md9kn7axci4c8qrnaav8ybo
foreign key (STUDENT_ID)
references PERSONS (ID)
Hibernate:
insert
into
PERSONS
(NAME, AGE)
values
(?, ?)
Hibernate:
insert
into
PERSONS
(NAME, AGE)
values
(?, ?)
Hibernate:
insert
into
STUDENTS
(CLASS_NAME, SCHOOL_NAME, STUDENT_ID)
values
(?, ?, ?)

数据库查寻结果:

执行testSelect()测试函数,执行结果及sql:

 Hibernate:
select
person0_.ID as ID1_0_,
person0_.NAME as NAME2_0_,
person0_.AGE as AGE3_0_,
person0_1_.CLASS_NAME as CLASS_NA2_1_,
person0_1_.SCHOOL_NAME as SCHOOL_N3_1_,
case
when person0_1_.STUDENT_ID is not null then 1
when person0_.ID is not null then 0
end as clazz_
from
PERSONS person0_
left outer join
STUDENTS person0_1_
on person0_.ID=person0_1_.STUDENT_ID
2
Hibernate:
select
student0_.STUDENT_ID as ID1_0_,
student0_1_.NAME as NAME2_0_,
student0_1_.AGE as AGE3_0_,
student0_.CLASS_NAME as CLASS_NA2_1_,
student0_.SCHOOL_NAME as SCHOOL_N3_1_
from
STUDENTS student0_
inner join
PERSONS student0_1_
on student0_.STUDENT_ID=student0_1_.ID
1
  • 使用union-subclass进行映射

在工程中复制包com.dx.hibernate06.extend,并命名新包名称为:com.dx.hibernate06.union.subclass

修改Person.hbm.xml:

 <?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 2017-6-8 15:16:00 by Hibernate Tools 3.5.0.Final -->
<hibernate-mapping package="com.dx.hibernate06.union.subclass">
<class name="Person" table="PERSONS">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="increment" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="age" type="java.lang.Integer">
<column name="AGE" />
</property>
<union-subclass name="Student" table="STUDENTS">
<property name="className" column="CLASS_NAME" type="string"></property>
<property name="schoolName" column="SCHOOL_NAME" type="string"></property>
</union-subclass>
</class>
</hibernate-mapping>

注意:

1)这里只需要指定union-subclass对应的表,及指定其独有的列;

2)Person的ID生成类型不能为identity,不能为native,这里采用的increment。

修改hibernate.cfg.xml,修改mapping节点指定文件路径:

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
。。。
<mapping resource="com/dx/hibernate06/union/subclass/Person.hbm.xml" />
</session-factory>
</hibernate-configuration>

测试:

在com.dx.hibernate06.union.subclass.TestMain.java中执行测试函数testInsert()(备注:该测试函数与上边测试函数一致),执行sql及结果:

 Hibernate: 

     create table PERSONS (
ID integer not null,
NAME varchar(255),
AGE integer,
primary key (ID)
) engine=InnoDB
Hibernate: create table STUDENTS (
ID integer not null,
NAME varchar(255),
AGE integer,
CLASS_NAME varchar(255),
SCHOOL_NAME varchar(255),
primary key (ID)
) engine=InnoDB
Hibernate:
select
max(ids_.mx)
from
( select
max(ID) as mx
from
STUDENTS
union
select
max(ID) as mx
from
PERSONS
) ids_
Hibernate:
insert
into
PERSONS
(NAME, AGE, ID)
values
(?, ?, ?)
Hibernate:
insert
into
STUDENTS
(NAME, AGE, CLASS_NAME, SCHOOL_NAME, ID)
values
(?, ?, ?, ?, ?)

数据库查寻结果:

执行testSelect()测试函数,执行结果及sql:

 Hibernate:
select
person0_.ID as ID1_0_,
person0_.NAME as NAME2_0_,
person0_.AGE as AGE3_0_,
person0_.CLASS_NAME as CLASS_NA1_1_,
person0_.SCHOOL_NAME as SCHOOL_N2_1_,
person0_.clazz_ as clazz_
from
( select
ID,
NAME,
AGE,
null as CLASS_NAME,
null as SCHOOL_NAME,
0 as clazz_
from
PERSONS
union
select
ID,
NAME,
AGE,
CLASS_NAME,
SCHOOL_NAME,
1 as clazz_
from
STUDENTS
) person0_
2
Hibernate:
select
student0_.ID as ID1_0_,
student0_.NAME as NAME2_0_,
student0_.AGE as AGE3_0_,
student0_.CLASS_NAME as CLASS_NA1_1_,
student0_.SCHOOL_NAME as SCHOOL_N2_1_
from
STUDENTS student0_
1

Hibernate(十一):映射继承关系的三种方案的更多相关文章

  1. 【hibernate】映射继承关系

    [hibernate]映射继承关系 转载:https://www.cnblogs.com/yangchongxing/p/10405151.html ========================= ...

  2. Django-多对多关系的三种创建方式-forms组件使用-cookie与session-08

    目录 表模型类多对多关系的三种创建方式 django forms 组件 登录功能手写推理过程 整段代码可以放过来 forms 组件使用 forms 后端定义规则并校验结果 forms 前端渲染标签组件 ...

  3. Hibernate使用中防止SQL注入的几种方案

    Hibernate使用中防止SQL注入的几种方案 Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数 ...

  4. SP避免Form重复提交的三种方案

    SP避免Form重复提交的三种方案  1) javascript ,设置一个变量,只允许提交一次.   <script language="javascript">  ...

  5. 【Win 10 应用开发】文件读写的三种方案

    本文老周就跟伙伴们探讨一下关于文件读写的方法.总得来说嘛,有三种方案可以用,而且每种方案都各有特色,也说不上哪种较好.反正你得记住老祖宗留给我们的大智慧——事无定法,灵活运用者为上. OK,咱们开始吧 ...

  6. [Linux]三种方案在Windows系统下安装ubuntu双系统(转)

    在学习linux的过程中,ubuntu无疑是初学者的最佳选择. 下面来列举给Windows系统安装ubuntu双系统的三种方法. 一.虚拟机安装(不推荐) 使用工具:Vmware 如果不是因为迫不得已 ...

  7. 关于Jenkins部署代码权限三种方案

    关于Jenkins部署代码权限三种方案 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.修改Jenkins进程用户为root [root@jenkins ~]# cat /etc ...

  8. 三种方案在Windows系统下安装ubuntu双系统

    一.虚拟机安装(不推荐) 使用工具:Vmware 如果不是因为迫不得已,比如Mac OS对硬件不兼容,Federa安装频繁出错,各种驱动不全等等,不推荐使用虚拟机安装. 个人感觉这是一种对操作系统的亵 ...

  9. MySQL冗余数据的三种方案

    一,为什么要冗余数据 互联网数据量很大的业务场景,往往数据库需要进行水平切分来降低单库数据量. 水平切分会有一个patition key,通过patition key的查询能够直接定位到库,但是非pa ...

随机推荐

  1. MYSQL数据库学习十三 使用MySQL常用函数

    13.1 字符串函数 对于针对字符串位置的操作,第一个位置被标记为1. 函数 功能 CONCAT(str1,str2...strn) 连接字符串str1.str2....strn INSERT(str ...

  2. 巧用linux版powershell,管理linux下的docker

    大家好,我把用powershell的docker马甲命令的好处,放在了页面下方,从第五章开始. powershell 传教士 原创文章 始于 2017-09-07 允许转载,但必须保留名字和出处,否则 ...

  3. Algorithm --> 求阶乘末尾0的个数

    求阶乘末尾0的个数 (1)给定一个整数N,那么N的阶乘N!末尾有多少个0?比如:N=10,N!=3628800,N!的末尾有2个0. (2)求N!的二进制表示中最低位为1的位置. 第一题 考虑哪些数相 ...

  4. Be Better , Be Better

    Be Better! 这不是一道题,只是我的flag.初三寒假,一个本应该对着计算机翻天覆雨的假期,我在鬼班撸高中课...其实感触是从初中课得来的.有些事,以前我说是我不懂,现在我不说不是我不懂.Ju ...

  5. Web安全概述

    互联网刚开始是安全的,但是伴随着黑客(Hacker)的诞生,互联网变得越来越不安全.任何一个事情都有两面性,黑客也有好有坏,好的黑客叫白帽子,坏的黑客叫黑帽子.与此同时,随着Web技术发展越来越成熟, ...

  6. alpha冲刺第六天

    一.合照 二.项目燃尽图 三.项目进展 主界面首页内容呈现 我的栏目之我的问题完成 我的栏目之我的提问完成 还是插不进去,然后打算先放一放,一直在一个地方纠结那么久脑子太乱 四.明日规划 问答界面问题 ...

  7. Beta No.5

    今天遇到的困难: 前端大部分代码由我们放逐的组员完成,这影响到了我们解决"Fragment碎片刷新时总产生的固定位置"的进程,很难找到源码对应 新加入的成员对界面代码不熟悉. 我们 ...

  8. C语言第三次作业总结

    本次作业的亮点 总体情况 大部分同学基本掌握了单层循环结构的写法,懂得了代码调试的过程 PTA通过率及作业质量都不错,希望再接再厉 推荐博客 黄毓颖 推荐理由:代码思路清晰,格式良好:调试过程相当形象 ...

  9. 冲刺No.3

    Alpha冲刺第三天 站立式会议 项目进展 今日团队对CSS与JS的基础知识进行了应用,并对网站的UI设计进行了讨论,对数据库设计进行了进一步的探讨,基本确立了各个表单的结构和内容.分割出项目基本模块 ...

  10. io多路复用(三)

    #!/usr/bin/env python # -*- coding:utf-8 -*- import socket sk1 = socket.socket() sk1.bind(('127.0.0. ...