Hibernate学习笔记之继承映射

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 products=query.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 products=query.list(); }
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) 全部查询出来。

你可能感兴趣的:(JAVA)