JPA继承方式
在JPA中,实体继承关系的映射策略有三种:
一:SINGLE_TABLE策略
二:JOINED策略
三:TABLE_PER_CLASS策略
在JPA中,默认的是使用第一种继承策略,即单表继承策略。
1.单表继承策略 SINGLE_TABLE
父类实体和子类实体共用一张数据库表,在表中通过一个辨别字段的值来区分不同类别的实体。
在父类中Entity的定义如下:
@Entity
@Table(name = "父表的名称")
@Inheritance(Strategy=InheritanceType.SINGLE_TABLE) //单表继承策略
@DiscriminatorColumn(name=”辨别字段列名”)
@DiscriminatorValue(父类实体辨别字段列值)
在子类中Entity的定义如下:
@Entity
@Table(name = "子表的名称")
@DiscriminatorValue("子类实体辨别字段列值")
举例如下:
1 @Entity 2 @Inheritance(strategy = InheritanceType.SINGLE_TABLE) 3 @Table(name = "WINDOW_FILE") 4 @DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING, length = 30) // 指定辨别字段的类型为String,长度30 5 @DiscriminatorValue("WindowFile") 6 public class WindowFile { 7 8 @Id 9 @GeneratedValue(strategy = GenerationType.AUTO) 10 private Integer id; 11 12 @Basic 13 @Column(name = "NAME") 14 private String name; 15 16 @Basic 17 @Column(name = "TYPE") 18 private String type; 19 20 @Basic 21 @Column(name = "DATE") 22 private Date date; 23 //省略get set 24 }
子类Folder定义
1 @Entity 2 @DiscriminatorValue("Folder") 3 public class Folder extends WindowFile { 4 5 @Basic 6 @Column(name = "FILE_COUNT") 7 private Integer fileCount; 8 //省略get set 9 }
子类Document定义
1 @Entity 2 @DiscriminatorValue("Document") 3 public class Document extends WindowFile { 4 5 @Basic 6 @Column(name = "SIZE") 7 private String size; 8 //省略get set 9 }
通过在父类中指定继承方式为@Inheritance(strategy = InheritanceType.SINGLE_TABLE),再指定辨别字段,通过辨别字段的值来区分父子实体。
生成的表结构如下:
WINDOW_FILE DISCRIMINATOR,ID,NAME,DATE,TYPE,SIZE,FILE_COUNT
当你使用WindowFile实体时,实际表的字段为 DISCRIMINATOR='WindowFile', 字段:SIZE 和 FILE_COUNT永远是空。
当使用Folder实体时,DISCRIMINATOR='Folder',字段:SIZE永远是空,字段:FILE_COUNT为实际set的值。
当使用Document实体时,DISCRIMINATOR='Document',字段:FILE_COUNT永远是空,字段:SIZE为实际set的值。
2.JOINED策略
父类实体和子类实体分别对应数据库中不同的表,父类定义的内容为子类们公共的属性,子类实体中定义的内容为扩展的属性。
在父类中Entity的定义如下:
@Entity
@Table(name = "父表的名称")
@Inheritance(Strategy=InheritanceType.JOINED) // JOINED继承策略
@DiscriminatorColumn(name=”辨别字段列名”)
在子类中Entity的定义如下:
@Entity
@Table(name = "子表的名称")
@DiscriminatorValue("子类实体辨别字段列值")
举例如下:
父类定义如下:
1 @Entity 2 @Table(name = "T_ANIMAL") 3 @Inheritance(strategy = InheritanceType.JOINED) 4 @DiscriminatorColumn(name = "AAA") // 辨别字段 AAA 5 public class Animal { 6 7 @Id 8 @Column(name = "ID") 9 @GeneratedValue(strategy = GenerationType.AUTO) 10 private Integer id; 11 12 @Column(name = "NAME") 13 private String name; 14 15 @Column(name = "COLOR") 16 private String color; 17 //省略get set 18 }
子类1Bird定义如下
@Entity @Table(name = "T_BIRD")
@DiscriminatorValue("Bird") public class Bird extends Animal { @Column(name = "SPEED") private String speed; //省略get set }
子类2Dog定义如下
@Entity @Table(name = "T_DOG") @DiscriminatorValue("Dog") public class Dog extends Animal { @Column(name = "LEGS") private Integer legs; //省略get set }
实际生成的表结构如下:
表:T_ANIMAL,字段: ID,COLOR,NAME
表:T_BIRD ,字段: SPEED,ID(既是外键,也是主键)
表:T_DOG,字段: LEGS,ID(既是外键,也是主键)
3.TABLE_PER_CLASS策略
父类实体和子类实体各自生成表,实体对应自己生成的表,子类实体对应的表的字段保存所有的属性,包括从父类实体中继承的属性。
在父类中Entity的定义如下:
@Entity
@Table(name = "父表的名称")
@Inheritance(Strategy=InheritanceType.TABLE_PER_CLASS) // TABLE_PER_CLASS继承策略
在子类中Entity的定义如下:
@Entity
@Table(name = "子表的名称")
举例如下:
父类定义如下:
@Entity @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @Table(name = "T_VEHICLE") public class Vehicle { // 基类 @Id // @GeneratedValue @Column(name = "ID") private Integer id; @Column(name = "SPEED") private Integer speed;// 速度 //省略get set }
子类定义如下:
@Entity @Table(name = "T_CAR") public class Car extends Vehicle { @Column(name = "ENGINE") private String engine;// 发动机 //省略get set }
一旦使用这种策略就意味着你不能使用AUTO generator 和IDENTITY generator,即主键值不能采用数据库自动生成。
实际表结构如下:
T_VEHICLE ID,SPEED
T_CAR ID,SPEED,ENGINE
总结:在使用JPA开发的过程的中,基本用到的@Inheritance(Strategy=InheritanceType.SINGE_TABLE)和@Inheritance(Strategy=InheritanceType.JOINED)这两种继承策略比较多。第三种在实际开发中目前没有用到过。
参考资料:http://zhuchengzzcc.iteye.com/blog/1679496