博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Hibernate(十一):映射继承关系的三种方案
阅读量:6831 次
发布时间:2019-06-26

本文共 12515 字,大约阅读时间需要 41 分钟。

  • 背景:

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

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

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

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

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

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

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

  • 使用subclass进行映射

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

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

1 
2 5
6
7
root
8
123456
9
com.mysql.jdbc.Driver
10
jdbc:mysql://localhost/hibernate_01
11 12
14
org.hibernate.dialect.MySQL5InnoDBDialect
15 16
true
17 18
true
19 20
update
21 22
thread
23 24
500
25
20
26
10
27
2000
28
2000
29
10
30 31
32 33
34
View Code

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

1 package com.dx.hibernate06.extend; 2  3 public class Person { 4     private Integer id; 5     private String name; 6     private Integer age; 7  8     public Person() { 9 10     }11 12     public Integer getId() {13         return id;14     }15 16     public void setId(Integer id) {17         this.id = id;18     }19 20     public String getName() {21         return name;22     }23 24     public void setName(String name) {25         this.name = name;26     }27 28     public Integer getAge() {29         return age;30     }31 32     public void setAge(Integer age) {33         this.age = age;34     }35 }
View Code

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

1 package com.dx.hibernate06.extend; 2  3 public class Student extends Person { 4     private String className; 5     private String schoolName; 6  7     public Student() { 8  9     }10 11     public String getClassName() {12         return className;13     }14 15     public void setClassName(String className) {16         this.className = className;17     }18 19     public String getSchoolName() {20         return schoolName;21     }22 23     public void setSchoolName(String schoolName) {24         this.schoolName = schoolName;25     }26 27 }
View Code

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

1 
2 4
5
6
7
8
9
10
11 12
13
14 15
16
17
18
19
20
21 22
23
24
25
26
27

注意:

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

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

添加测试类TestMain.java:

1 package com.dx.hibernate06.extend; 2  3 import org.hibernate.Session; 4 import org.hibernate.SessionFactory; 5 import org.hibernate.Transaction; 6 import org.hibernate.boot.Metadata; 7 import org.hibernate.boot.MetadataSources; 8 import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl; 9 import org.hibernate.boot.registry.StandardServiceRegistry;10 import org.hibernate.boot.registry.StandardServiceRegistryBuilder;11 import org.junit.After;12 import org.junit.Before;13 import org.junit.Test;14 15 public class TestMain {16     private SessionFactory sessionFactory = null;17     private Session session = null;18     private Transaction transaction = null;19 20     @Before21     public void init() {22         StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().configure().build();23         Metadata metadata = new MetadataSources(standardRegistry).getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyComponentPathImpl.INSTANCE).build();24 25         sessionFactory = metadata.getSessionFactoryBuilder().build();26         session = sessionFactory.getCurrentSession();27         transaction = session.beginTransaction();28     }29 30 31     @After32     public void destory() {33         transaction.commit();34         session.close();35         sessionFactory.close();36     }37 }
View Code

测试:

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

1     @Test 2     public void testInsert() { 3         Person person = new Person(); 4         person.setName("person1"); 5         person.setAge(27); 6  7         Student student = new Student(); 8         student.setName("student1"); 9         student.setAge(22);10         student.setClassName("class-1");11         student.setSchoolName("浙江大学");12 13         session.save(person);14         session.save(student);15     }

测试执行sql:

1 Hibernate:  2      3     create table PERSONS ( 4        ID integer not null auto_increment, 5         TYPE varchar(255) not null, 6         NAME varchar(255), 7         AGE integer, 8         CLASS_NAME varchar(255), 9         SCHOOL_NAME varchar(255),10         primary key (ID)11     ) engine=InnoDB12 Hibernate: 13     insert 14     into15         PERSONS16         (NAME, AGE, TYPE) 17     values18         (?, ?, 'person')19 Hibernate: 20     insert 21     into22         PERSONS23         (NAME, AGE, CLASS_NAME, SCHOOL_NAME, TYPE) 24     values25         (?, ?, ?, ?, 'student')
View Code

数据库查寻结果:

添加测试函数2:

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

执行sql及结果:

1 Hibernate:  2     select 3         person0_.ID as ID1_0_, 4         person0_.NAME as NAME3_0_, 5         person0_.AGE as AGE4_0_, 6         person0_.CLASS_NAME as CLASS_NA5_0_, 7         person0_.SCHOOL_NAME as SCHOOL_N6_0_, 8         person0_.TYPE as TYPE2_0_  9     from10         PERSONS person0_11 212 Hibernate: 13     select14         student0_.ID as ID1_0_,15         student0_.NAME as NAME3_0_,16         student0_.AGE as AGE4_0_,17         student0_.CLASS_NAME as CLASS_NA5_0_,18         student0_.SCHOOL_NAME as SCHOOL_N6_0_ 19     from20         PERSONS student0_ 21     where22         student0_.TYPE='student'23 1
  • 使用jioned-subclass进行映射

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

修改Person.hbm.xml:

1 
2 4
5
6
7
8
9
10
11 12
13
14
15
16
17
18 19
20
21
22
23
24
25
26
27

注意:

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

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

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

。。。

测试:

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

1 Hibernate:  2      3     create table PERSONS ( 4        ID integer not null auto_increment, 5         NAME varchar(255), 6         AGE integer, 7         primary key (ID) 8     ) engine=InnoDB 9 Hibernate: 10     11     create table STUDENTS (12        STUDENT_ID integer not null,13         CLASS_NAME varchar(255),14         SCHOOL_NAME varchar(255),15         primary key (STUDENT_ID)16     ) engine=InnoDB17 Hibernate: 18     19     alter table STUDENTS 20        add constraint FK3md9kn7axci4c8qrnaav8ybo 21        foreign key (STUDENT_ID) 22        references PERSONS (ID)23 Hibernate: 24     insert 25     into26         PERSONS27         (NAME, AGE) 28     values29         (?, ?)30 Hibernate: 31     insert 32     into33         PERSONS34         (NAME, AGE) 35     values36         (?, ?)37 Hibernate: 38     insert 39     into40         STUDENTS41         (CLASS_NAME, SCHOOL_NAME, STUDENT_ID) 42     values43         (?, ?, ?)
View Code

数据库查寻结果:

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

1 Hibernate:  2     select 3         person0_.ID as ID1_0_, 4         person0_.NAME as NAME2_0_, 5         person0_.AGE as AGE3_0_, 6         person0_1_.CLASS_NAME as CLASS_NA2_1_, 7         person0_1_.SCHOOL_NAME as SCHOOL_N3_1_, 8         case  9             when person0_1_.STUDENT_ID is not null then 1 10             when person0_.ID is not null then 0 11         end as clazz_ 12     from13         PERSONS person0_ 14     left outer join15         STUDENTS person0_1_ 16             on person0_.ID=person0_1_.STUDENT_ID17 218 Hibernate: 19     select20         student0_.STUDENT_ID as ID1_0_,21         student0_1_.NAME as NAME2_0_,22         student0_1_.AGE as AGE3_0_,23         student0_.CLASS_NAME as CLASS_NA2_1_,24         student0_.SCHOOL_NAME as SCHOOL_N3_1_ 25     from26         STUDENTS student0_ 27     inner join28         PERSONS student0_1_ 29             on student0_.STUDENT_ID=student0_1_.ID30 1
  • 使用union-subclass进行映射

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

修改Person.hbm.xml:

1 
2 4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

注意:

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

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

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

1 
2 5
6
7 。。。 8
9
10

测试:

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

1 Hibernate:  2      3     create table PERSONS ( 4        ID integer not null, 5         NAME varchar(255), 6         AGE integer, 7         primary key (ID) 8     ) engine=InnoDB 9 Hibernate: 10     11     create table STUDENTS (12        ID integer not null,13         NAME varchar(255),14         AGE integer,15         CLASS_NAME varchar(255),16         SCHOOL_NAME varchar(255),17         primary key (ID)18     ) engine=InnoDB19 Hibernate: 20     select21         max(ids_.mx) 22     from23         ( select24             max(ID) as mx 25         from26             STUDENTS 27         union28         select29             max(ID) as mx 30         from31             PERSONS 32     ) ids_33 Hibernate: 34     insert 35     into36         PERSONS37         (NAME, AGE, ID) 38     values39         (?, ?, ?)40 Hibernate: 41     insert 42     into43         STUDENTS44         (NAME, AGE, CLASS_NAME, SCHOOL_NAME, ID) 45     values46         (?, ?, ?, ?, ?)
View Code

数据库查寻结果:

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

1 Hibernate:  2     select 3         person0_.ID as ID1_0_, 4         person0_.NAME as NAME2_0_, 5         person0_.AGE as AGE3_0_, 6         person0_.CLASS_NAME as CLASS_NA1_1_, 7         person0_.SCHOOL_NAME as SCHOOL_N2_1_, 8         person0_.clazz_ as clazz_  9     from10         ( select11             ID,12             NAME,13             AGE,14             null as CLASS_NAME,15             null as SCHOOL_NAME,16             0 as clazz_ 17         from18             PERSONS 19         union20         select21             ID,22             NAME,23             AGE,24             CLASS_NAME,25             SCHOOL_NAME,26             1 as clazz_ 27         from28             STUDENTS 29     ) person0_30 231 Hibernate: 32     select33         student0_.ID as ID1_0_,34         student0_.NAME as NAME2_0_,35         student0_.AGE as AGE3_0_,36         student0_.CLASS_NAME as CLASS_NA1_1_,37         student0_.SCHOOL_NAME as SCHOOL_N2_1_ 38     from39         STUDENTS student0_40 1

 

转载地址:http://uvtkl.baihongyu.com/

你可能感兴趣的文章
搭建交叉编译环境
查看>>
linux下tar压缩/解压的使用(tar) 压缩/解压
查看>>
菜单each+hover
查看>>
乐观锁和悲观锁【转】
查看>>
抵制长假,呼唤年假!
查看>>
Linux的安装
查看>>
修復 “Failed to bring up eth0″ in Ubuntu virtualbox
查看>>
发现linux主机再用代理上网的情况下不能用wget从外网下载资源
查看>>
查找链表中倒数第k个结点
查看>>
不只是技术!成为IT经理必备的十大软技能
查看>>
基于AgileEAS.NET SOA 平台SAAS架构技术的开源分销ERP系统-SmartERP.NET下载配置说明
查看>>
16个时髦的扁平化设计的 HTML5 & CSS3 网站模板
查看>>
c++工厂模式(Factory method)
查看>>
[RGEOS]空间拓扑关系
查看>>
java_queue
查看>>
JavaScript escape encodeURI
查看>>
Exchange模式功能
查看>>
Tomcat性能优化(二) 启动参数设置
查看>>
Today See>
查看>>
kiddouk/redisco
查看>>