Hibernate支持三种类型的继承关系:
每个具体类一张表(Table per concrete class):表与子类之间的独立一对一关系。
每个子类一张表(Table per subclass):每个子类对应一张子表,并与主类共享主表。
每个类分层结构一张表(Table per class hierarchy):表与类的一对多关系。
实例场景:产品(Product)、DVD和书籍(Book)
1、每个具体类一张表。注解使用@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
表结构如下:
测试方法:
Hibernate生成的Sql语句:
Hibernate: insert into t_product (manufacturer, name, id) values (?, ?, ?)
Hibernate: insert into t_product (manufacturer, name, id) values (?, ?, ?)
Hibernate: insert into t_dvd (manufacturer, name, region_code, id) values (?, ?, ?, ?)
Hibernate: insert into t_dvd (manufacturer, name, region_code, id) values (?, ?, ?, ?)
Hibernate: insert into t_book (manufacturer, name, page_count, id) values (?, ?, ?, ?)
Hibernate: insert into t_book (manufacturer, name, page_count, id) values (?, ?, ?, ?)
测试方法:
Hibernate生成的Sql语句:
select product0_.id as id6_,
product0_.manufacturer as manufact2_6_,
product0_.name as name6_,
product0_.page_count as page1_7_,
product0_.region_code as region1_8_,
product0_.clazz_ as clazz_
from (select manufacturer,
null as page_count,
null as region_code,
name,
id,
0 as clazz_
from t_product
union all
select manufacturer,
page_count,
null as region_code,
name,
id,
1 as clazz_
from t_book
union all
select manufacturer,
null as page_count,
region_code,
name,
id,
2 as clazz_
from t_dvd) product0_
Hibernate会自动把t_product,t_book和t_dvd表里的内容全部查询出来,这是因为Product类也是实体,在数据库中也有对应的表。如果不希望Product类成为映射实体,可以将其定义成抽象类(即public abstract class Product {})或者使用 @MappedSuperclass 注解,这样测试方法inheritanceTestQuery()对应Hibernate生成的sql语句为:
select product0_.id as id6_,
product0_.manufacturer as manufact2_6_,
product0_.name as name6_,
product0_.page_count as page1_7_,
product0_.region_code as region1_8_,
product0_.clazz_ as clazz_
from (select manufacturer,
page_count,
null as region_code,
name,
id,
1 as clazz_
from t_book
union all
select manufacturer,
null as page_count,
region_code,
name,
id,
2 as clazz_
from t_dvd) product0_
可见Hibernate只从t_dvd和t_book里取数据。
2、每个子类一张表。注解使用@Inheritance(strategy=InheritanceType.JOINED)
表结构
执行测试方法inheritanceTestInsert();
Hibernate生成的Sql语句:
Hibernate: insert into t_product (manufacturer, name, id) values (?, ?, ?)
Hibernate: insert into t_product (manufacturer, name, id) values (?, ?, ?)
Hibernate: insert into t_product (manufacturer, name, id) values (?, ?, ?)
Hibernate: insert into t_dvd (region_code, id) values (?, ?)
Hibernate: insert into t_product (manufacturer, name, id) values (?, ?, ?)
Hibernate: insert into t_dvd (region_code, id) values (?, ?)
Hibernate: insert into t_product (manufacturer, name, id) values (?, ?, ?)
Hibernate: insert into t_book (page_count, id) values (?, ?)
Hibernate: insert into t_product (manufacturer, name, id) values (?, ?, ?)
Hibernate: insert into t_book (page_count, id) values (?, ?)
执行测试方法inheritanceTestQuery() ;
Hibernate生成的Sql语句:
select product0_.id as id6_,
product0_.manufacturer as manufact2_6_,
product0_.name as name6_,
product0_1_.page_count as page2_7_,
product0_2_.region_code as region2_8_,
case
when product0_1_.id is not null then
1
when product0_2_.id is not null then
2
when product0_.id is not null then
0
end as clazz_
from t_product product0_
left outer join t_book product0_1_
on product0_.id = product0_1_.id
left outer join t_dvd product0_2_
on product0_.id = product0_2_.id
Hibernate会自动把t_product、t_book与t_dvd表里的内容全部连接查询出来。
3、每个类分层结构一张表。注解使用@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
表结构
执行测试方法inheritanceTestInsert();
Hibernate生成的sql语句:
Hibernate: insert into t_product (manufacturer, name, category, id) values (?, ?, 'product', ?)
Hibernate: insert into t_product (manufacturer, name, category, id) values (?, ?, 'product', ?)
Hibernate: insert into t_product (manufacturer, name, region_code, category, id) values (?, ?, ?, 'dvd', ?)
Hibernate: insert into t_product (manufacturer, name, region_code, category, id) values (?, ?, ?, 'dvd', ?)
Hibernate: insert into t_product (manufacturer, name, page_count, category, id) values (?, ?, ?, 'book', ?)
Hibernate: insert into t_product (manufacturer, name, page_count, category, id) values (?, ?, ?, 'book', ?)
可见,Product、DVD和Book对应的记录都插入了t_product表中,并通过category字段来区分。
执行测试方法
Hibernate生成的Sql语句:
select book0_.id as id6_,
book0_.manufacturer as manufact3_6_,
book0_.name as name6_,
book0_.page_count as page5_6_
from t_product book0_
where book0_.category = 'book'
Hibernate会根据配置自动进行类型识别,把t_product表中category=book的数据(Book) 全部查询出来。