JPA学习记录三( @DiscriminatorColumn用法)

来源:互联网 发布:自干五 小粉红 知乎 编辑:程序博客网 时间:2024/05/17 23:30
[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. 1、多个entity对应同一张表,用一个字段区分  
  2. @Entity  
  3. @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)  
  4. @Table(name = "GRP_UNITINFO")  
  5. @Inheritance(strategy = InheritanceType.SINGLE_TABLE)  
  6. @DiscriminatorColumn(name = "GROUPFLG", discriminatorType = DiscriminatorType.STRING)  
  7. @DiscriminatorOptions(force=true)  
  8. @DiscriminatorValue(value = "2")  
  9. public class Unitinfo extends BaseActiveEntity implements java.io.Serializable {  

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. @Entity  
  2. @Table(name = "GRP_UNITINFO")  
  3. @Inheritance(strategy = InheritanceType.SINGLE_TABLE)  
  4. @DiscriminatorColumn(name = "GROUPFLG", discriminatorType = DiscriminatorType.STRING)  
  5. @DiscriminatorOptions(force=true)  
  6. @DiscriminatorValue(value = "1")  
  7. public class Subgroup extends BaseActiveEntity implements java.io.Serializable{  

[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. @Entity  
  2. @Cache(usage=CacheConcurrencyStrategy.READ_WRITE)  
  3. @Table(name = "GRP_UNITINFO")  
  4. @Inheritance(strategy = InheritanceType.SINGLE_TABLE)  
  5. @DiscriminatorColumn(name = "GROUPFLG", discriminatorType = DiscriminatorType.STRING)  
  6. @DiscriminatorOptions(force=true)  
  7. @DiscriminatorValue(value = "0")  
[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. @DiscriminatorOptions(force=true)可以用@ForceDiscriminator(org.hibernate.annotations.<em>ForceDiscriminator</em>)代替  
  2.   
  3. @DiscriminatorColumn@DiscriminatorOptions(force=true)在使用时,大部分情况下应该一起使用才不会出问题,但为什么Hibernate却必须在使用时要指定@DiscriminatorOptions,而且@DiscriminatorOptions中force的默认值还是false呢?  
  4. 当使用Discriminator应用于单表时,才需要使用@DiscriminatorOptions(force=true),应用于JOIN_TABLE时,不需要此注解  
  5.   
  6. 原文详见:http://stackoverflow.com/questions/12199874/about-the-use-of-forcediscriminator-discriminatoroptionsforce-true  
  7.   
  8. 首先看一下最顶层的父类EmployeeEO,代码如下所示。  
  9.   
  10.   
  11.   
  12. EmployeeEO  
  13.   
  14. @Entity  
  15.   
  16. @Table(name = "tb_employee")  
  17.   
  18. /**继承映射策略*/  
  19.   
  20. @Inheritance(strategy=InheritanceType.SINGLE_TABLE)  
  21.   
  22. /**标识字段定义*/  
  23.   
  24. @DiscriminatorColumn(  
  25.   
  26. name="employee_type",discriminatorType=DiscriminatorType.STRING  
  27.   
  28. )  
  29.   
  30. /**该类的标识*/  
  31.   
  32. @DiscriminatorValue("employee")  
  33.   
  34. public class EmployeeEO implements Serializable {  
  35.   
  36.           
  37.   
  38.          private Integer id;  
  39.   
  40.          private String name;  
  41.   
  42.           
  43.   
  44.          @Id  
  45.   
  46.          @GeneratedValue(strategy = GenerationType.AUTO)  
  47.   
  48.          public Integer getId() {  
  49.   
  50.                    return id;  
  51.   
  52.          }  
  53.   
  54.          public void setId(Integer id) {  
  55.   
  56.                    this.id = id;  
  57.   
  58.          }  
  59.   
  60.          public String getName() {  
  61.   
  62.                    return name;  
  63.   
  64.          }  
  65.   
  66.          public void setName(String name) {  
  67.   
  68.                    this.name = name;  
  69.   
  70.          }  
  71.   
  72. }  
  73.   
  74. 在最顶层的父类中,通常要做以下映射:  
  75.   
  76. l         使用@Entity注释,标识该类以及所有的子类都映射到指定的表中,如果不标注,也可使用默认值。  
  77.   
  78. l         使用@Inheritance注释,标识该类的子类继承映射的方式,该注释的定义如一下所示:  
  79.   
  80. @Target({TYPE}) @Retention(RUNTIME)  
  81.   
  82. public @interface Inheritance {  
  83.   
  84. InheritanceType strategy() default SINGLE_TABLE;  
  85.   
  86. }  
  87.   
  88. 其中,InheritanceType有三种类型,即7.4.2小节中讲述的三种类型,三种类型定义为常量,默认为SINGLE_TABLE。  
  89.   
  90. public enum InheritanceType  
  91.   
  92. { SINGLE_TABLE, JOINED, TABLE_PER_CLASS };  
  93.   
  94. SINGLE_TABLE表示继承关系的实体保存在一个表;JOINED表示每个实体子类保存在一个表;TABLE_PER_CLASS表示每个实体类保存在一个表。这里使用的是第一种策略,所以定义的代码如下所示:  
  95.   
  96. @Inheritance(strategy=InheritanceType.SINGLE_TABLE)  
  97.   
  98. l         使用@DiscriminatorColumn注释,标识改继承层次上所区别每个实体的类型字段。它的定义如以下所示:  
  99.   
  100. @Target({TYPE}) @Retention(RUNTIME)  
  101.   
  102. public @interface DiscriminatorColumn {  
  103.   
  104. String name() default "DTYPE";  
  105.   
  106. DiscriminatorType discriminatorType() default STRING;  
  107.   
  108. String columnDefinition() default "";  
  109.   
  110. int length() default 31;  
  111.   
  112. }  
  113.   
  114. 其中,@DiscriminatorColumn在使用时要注意以下这些问题。  
  115.   
  116. 1@DiscriminatorColumn只能标注在顶层的类中,而不能标注在子类中。  
  117.   
  118. 2@DiscriminatorColumn只在继承策略为“SINGLE_TABLE”和“JOINED”时使用。  
  119.   
  120. 3)name属性表示所标识具体类型的字段名称,默认为“DTYPE”,例如本例中使用的是字段“employee_type”,所以定义如下。  
  121.   
  122. @DiscriminatorColumn(name="employee_type")  
  123.   
  124. 4)discriminatorType属性表示标识值的类型,默认为STRING字符串。它使用的枚举类型如下所示。  
  125.   
  126. public enum DiscriminatorType { STRING, CHAR, INTEGER };  
  127.   
  128. 也就是说,标识值可以为String、Char或者Integer  
  129.   
  130. 5)columnDefinition属性表示生成字段的DDL语句,与@Column中的columnDefinition属性类似。  
  131.   
  132. 6)length属性表示为标识值的长度,默认为31。该属性只在使用DiscriminatorType. STRING时才需要设置。  
  133.   
  134. l         使用@DiscriminatorValue注释,标注该实体类所实体标识字段的值,它的定义如下:  
  135.   
  136. @Target({TYPE}) @Retention(RUNTIME)  
  137.   
  138. public @interface DiscriminatorValue {  
  139.   
  140. String value();  
  141.   
  142. }  
  143.   
  144. value的值表示所该实体的标注值。例如,标识字段“employee_type”的值为“employee”时可以认为是EmployeeEO实体。代码设置如下所示:  
  145.   
  146. @DiscriminatorValue("employee")  
  147.   
  148.   
  149. <pre name="code" class="plain"2、在JPA中,实体继承关系的映射策略共有三种:单表继承策略(table per class)、Joined策略(table per subclass)和Table_PER_Class策略。  
  150.   
  151.    
  152.   
  153. 1.单表继承策略  
  154.   
  155.      
  156.   
  157.     单表继承策略,父类实体和子类实体共用一张数据库表,在表中通过一列辨别字段来区别不同类别的实体。具体做法如下:  
  158.   
  159. a.在父类实体的@Entity注解下添加如下的注解:  
  160.   
  161. @Inheritance(Strategy=InheritanceType.SINGLE_TABLE)  
  162. @DiscriminatorColumn(name=”辨别字段列名”)  
  163. @DiscriminatorValue(父类实体辨别字段列值)  
  164.   
  165.    
  166.   
  167. b.在子类实体的@Entity注解下添加如下的注解:  
  168.   
  169. @DiscriminatorValue(子类实体辨别字段列值)   

  在JPA中,实体继承关系的映射策略共有三种:单表继承策略(table per class)、Joined策略(table per subclass)和Table_PER_Class策略。

 

1.单表继承策略

   

    单表继承策略,父类实体和子类实体共用一张数据库表,在表中通过一列辨别字段来区别不同类别的实体。具体做法如下:

a.在父类实体的@Entity注解下添加如下的注解:

@Inheritance(Strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name=”辨别字段列名”)
@DiscriminatorValue(父类实体辨别字段列值)

 

b.子类实体的@Entity注解下添加如下的注解:

@DiscriminatorValue(子类实体辨别字段列值) 

 定义了一个父类

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@Table(name = "WINDOW_FILE")
@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING, length = 30)
@DiscriminatorValue("WindowFile")
public class WindowFile {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Basic
    @Column(name = "NAME")
    private String name;

    @Basic
    @Column(name = "TYPE")
    private String type;

    @Basic
    @Column(name = "DATE")
    private Date date;
    //省略get set

}

后定义2个子类

@Entity
@DiscriminatorValue("Folder")
public class Folder extends WindowFile {

    @Basic
    @Column(name = "FILE_COUNT")
    private Integer fileCount;
    //省略get set
}

@Entity
@DiscriminatorValue("Document")
public class Document extends WindowFile {

    @Basic
    @Column(name = "SIZE")
    private String size;
    //省略get set
}

 以上通过列DISCRIMINATOR的不同,区分具体父子实体。

 

实际表结构如下:

WINDOW_FILE  DISCRIMINATOR,ID,NAME,DATE,TYPE,SIZE,FILE_COUNT

 

当你使用WindowFile实体时,实际表的字段为DISCRIMINATOR='WindowFile',SIZE与FILE_COUNT永远是空

当使用Folder实体时,DISCRIMINATOR='Folder',SIZE永远是空,FILE_COUNT为实际值。

Document同理,与Folder类似。

2.Joined策略

父类实体和子类实体分别对应数据库中不同的表,子类实体的表中只存在其扩展的特殊属性,父类的公共属性保存在父类实体映射表中。具体做法:

@Inheritance(Strategy=InheritanceType.JOINED)

子类实体不需要特殊说明。

@Entity@Table(name = "T_ANIMAL")@Inheritance(strategy = InheritanceType.JOINED)public class Animal {    @Id    @Column(name = "ID")    @GeneratedValue(strategy = GenerationType.AUTO)    private Integer id;    @Column(name = "NAME")    private String name;    @Column(name = "COLOR")    private String color;    //省略get set}

@Entity@Table(name = "T_BIRD")@PrimaryKeyJoinColumn(name = "BIRD_ID")public class Bird extends Animal {    @Column(name = "SPEED")    private String speed;    //省略get set}

@Entity@Table(name = "T_DOG")@PrimaryKeyJoinColumn(name = "DOG_ID")public class Dog extends Animal {    @Column(name = "LEGS")    private Integer legs;    //省略get set}

实际表结构如下:

T_ANIMAL  ID,COLOR,NAME

T_BIRD  SPEED,BIRD(既是外键,也是主键)

T_DOG  LEGS,DOG_ID(既是外键,也是主键)

3.Table_PER_Class策略:

Table_PER_Class策略,父类实体和子类实体每个类分别对应一张数据库中的表,子类表中保存所有属性,包括从父类实体中继承的属性。具体做法:

只需在父类实体的@Entity注解下添加如下注解:

@Inheritance(Strategy=InheritanceType.TABLE_PER_CLASS)

@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

转载:http://blog.csdn.net/jiana227/article/details/46429235

                                             
0 0
原创粉丝点击