@DiscriminatorColumn用法

1、多個entity對應同一張表,用一個字段區分
@Entity
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@Table(name = "GRP_UNITINFO")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "GROUPFLG", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorOptions(force=true)
@DiscriminatorValue(value = "2")
public class Unitinfo extends BaseActiveEntity implements java.io.Serializable {

@Entity
@Table(name = "GRP_UNITINFO")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "GROUPFLG", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorOptions(force=true)
@DiscriminatorValue(value = "1")
public class Subgroup extends BaseActiveEntity implements java.io.Serializable{

@Entity
@Cache(usage=CacheConcurrencyStrategy.READ_WRITE)
@Table(name = "GRP_UNITINFO")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "GROUPFLG", discriminatorType = DiscriminatorType.STRING)
@DiscriminatorOptions(force=true)
@DiscriminatorValue(value = "0")
@DiscriminatorOptions(force=true)可以用@ForceDiscriminator(org.hibernate.annotations.<em>ForceDiscriminator</em>)代替

@DiscriminatorColumn和@DiscriminatorOptions(force=true)在使用時,大部分情況下應該一起使用纔不會出問題,但爲什麼Hibernate卻必須在使用時要指定@DiscriminatorOptions,而且@DiscriminatorOptions中force的默認值還是false呢?
當使用Discriminator應用於單表時,才需要使用@DiscriminatorOptions(force=true),應用於JOIN_TABLE時,不需要此註解

原文詳見:http://stackoverflow.com/questions/12199874/about-the-use-of-forcediscriminator-discriminatoroptionsforce-true

首先看一下最頂層的父類EmployeeEO,代碼如下所示。



EmployeeEO

@Entity

@Table(name = "tb_employee")

/**繼承映射策略*/

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

/**標識字段定義*/

@DiscriminatorColumn(

name="employee_type",discriminatorType=DiscriminatorType.STRING

)

/**該類的標識*/

@DiscriminatorValue("employee")

public class EmployeeEO implements Serializable {

        

         private Integer id;

         private String name;

        

         @Id

         @GeneratedValue(strategy = GenerationType.AUTO)

         public Integer getId() {

                   return id;

         }

         public void setId(Integer id) {

                   this.id = id;

         }

         public String getName() {

                   return name;

         }

         public void setName(String name) {

                   this.name = name;

         }

}

在最頂層的父類中,通常要做以下映射:

l         使用@Entity註釋,標識該類以及所有的子類都映射到指定的表中,如果不標註,也可使用默認值。

l         使用@Inheritance註釋,標識該類的子類繼承映射的方式,該註釋的定義如一下所示:

@Target({TYPE}) @Retention(RUNTIME)

public @interface Inheritance {

InheritanceType strategy() default SINGLE_TABLE;

}

其中,InheritanceType有三種類型,即7.4.2小節中講述的三種類型,三種類型定義爲常量,默認爲SINGLE_TABLE。

public enum InheritanceType

{ SINGLE_TABLE, JOINED, TABLE_PER_CLASS };

SINGLE_TABLE表示繼承關係的實體保存在一個表;JOINED表示每個實體子類保存在一個表;TABLE_PER_CLASS表示每個實體類保存在一個表。這裏使用的是第一種策略,所以定義的代碼如下所示:

@Inheritance(strategy=InheritanceType.SINGLE_TABLE)

l         使用@DiscriminatorColumn註釋,標識改繼承層次上所區別每個實體的類型字段。它的定義如以下所示:

@Target({TYPE}) @Retention(RUNTIME)

public @interface DiscriminatorColumn {

String name() default "DTYPE";

DiscriminatorType discriminatorType() default STRING;

String columnDefinition() default "";

int length() default 31;

}

其中,@DiscriminatorColumn在使用時要注意以下這些問題。

(1)@DiscriminatorColumn只能標註在頂層的類中,而不能標註在子類中。

(2)@DiscriminatorColumn只在繼承策略爲“SINGLE_TABLE”和“JOINED”時使用。

(3)name屬性表示所標識具體類型的字段名稱,默認爲“DTYPE”,例如本例中使用的是字段“employee_type”,所以定義如下。

@DiscriminatorColumn(name="employee_type")

(4)discriminatorType屬性表示標識值的類型,默認爲STRING字符串。它使用的枚舉類型如下所示。

public enum DiscriminatorType { STRING, CHAR, INTEGER };

也就是說,標識值可以爲String、Char或者Integer

(5)columnDefinition屬性表示生成字段的DDL語句,與@Column中的columnDefinition屬性類似。

(6)length屬性表示爲標識值的長度,默認爲31。該屬性只在使用DiscriminatorType. STRING時才需要設置。

l         使用@DiscriminatorValue註釋,標註該實體類所實體標識字段的值,它的定義如下:

@Target({TYPE}) @Retention(RUNTIME)

public @interface DiscriminatorValue {

String value();

}

value的值表示所該實體的標註值。例如,標識字段“employee_type”的值爲“employee”時可以認爲是EmployeeEO實體。代碼設置如下所示:

@DiscriminatorValue("employee")


<pre name="code" class="plain"> 2、在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(子類實體辨別字段列值) 

  在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



發佈了55 篇原創文章 · 獲贊 13 · 訪問量 36萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章