Hibernate支持三种类型的继承关系:
每个具体类一张表(Table per concrete class):表与子类之间的独立一对一关系。
每个子类一张表(Table per subclass):每个子类对应一张子表,并与主类共享主表。
每个类分层结构一张表(Table per class hierarchy):表与类的一对多关系。
实例场景:产品(Product)、DVD和书籍(Book)
1、每个具体类一张表。注解使用@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
表结构如下:
@Entity @Table(name="t_product") @Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) public class Product { private Integer id; private String manufacturer;//生产商 private String name;//商品名 @Id @GeneratedValue(strategy=GenerationType.AUTO) public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getManufacturer() { return manufacturer; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } public String getName() { return name; } public void setName(String name) { this.name = name; } } @Entity @Table(name="t_dvd") public class DVD extends Product { private String regionCode; @Column(name="region_code") public String getRegionCode() { return regionCode; } public void setRegionCode(String regionCode) { this.regionCode = regionCode; } } @Entity @Table(name="t_book") public class Book extends Product { private Integer pageCount; @Column(name="page_count") public Integer getPageCount() { return pageCount; } public void setPageCount(Integer pageCount) { this.pageCount = pageCount; } }
测试方法:
public void inheritanceTestInsert() { Product product1=new Product(); product1.setName("书籍"); product1.setManufacturer("出版商"); Product product2=new Product(); product2.setName("食品"); product2.setManufacturer("农场"); DVD dvd1=new DVD(); dvd1.setName("泰山"); dvd1.setManufacturer("北影"); dvd1.setRegionCode("美国"); DVD dvd2=new DVD(); dvd2.setName("让子弹飞"); dvd2.setManufacturer("大幅度"); dvd2.setRegionCode("中国"); Book book1=new Book(); book1.setName("大话"); book1.setManufacturer("备有"); book1.setPageCount(10000); Book book2=new Book(); book2.setName("托福"); book2.setManufacturer("科技"); book2.setPageCount(23434); Transaction tx=session.beginTransaction(); session.save(product1); session.save(product2); session.save(dvd1); session.save(dvd2); session.save(book1); session.save(book2); tx.commit(); }
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 (?, ?, ?, ?)
测试方法:
public void inheritanceTestQuery() { Query query=session.createQuery("from Product"); List
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)
表结构
@Entity @Table(name="t_product") @Inheritance(strategy=InheritanceType.JOINED) public class Product { private Integer id; private String manufacturer;//生产商 private String name;//商品名 @Id @GeneratedValue(strategy=GenerationType.AUTO) public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getManufacturer() { return manufacturer; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } public String getName() { return name; } public void setName(String name) { this.name = name; } } @Entity @Table(name="t_dvd") public class DVD extends Product { private String regionCode; @Column(name="region_code") public String getRegionCode() { return regionCode; } public void setRegionCode(String regionCode) { this.regionCode = regionCode; } } @Entity @Table(name="t_book") public class Book extends Product { private Integer pageCount; @Column(name="page_count") public Integer getPageCount() { return pageCount; } public void setPageCount(Integer pageCount) { this.pageCount = pageCount; } }
执行测试方法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)
表结构
@Entity @Table(name="t_product") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="category",discriminatorType=DiscriminatorType.STRING)//定义用于区分的列名为category,列类型为String @DiscriminatorValue("product")//可选,指定Product类对应的记录的category字段的值为“product”,默认值为类名,即"Product" public class Product { private Integer id; private String manufacturer;//生产商 private String name;//商品名 @Id @GeneratedValue(strategy=GenerationType.AUTO) public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getManufacturer() { return manufacturer; } public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; } public String getName() { return name; } public void setName(String name) { this.name = name; } } @Entity @DiscriminatorValue("dvd")//可选,指定DVD类对应的记录的category字段的值为“dvd”,默认值为类名,即"DVD" public class DVD extends Product { private String regionCode; @Column(name="region_code") public String getRegionCode() { return regionCode; } public void setRegionCode(String regionCode) { this.regionCode = regionCode; } } @Entity @DiscriminatorValue("book")//可选,指定Book类对应的记录的category字段的值为“book”,默认值为类名,即"Book" public class Book extends Product { private Integer pageCount; @Column(name="page_count") public Integer getPageCount() { return pageCount; } public void setPageCount(Integer pageCount) { this.pageCount = pageCount; } }
执行测试方法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字段来区分。
执行测试方法
public void inheritanceTestQuery() { Query query=session.createQuery("from Book"); List
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) 全部查询出来。