列舉型別在JPA中的使用

又是火星人發表於2020-12-01

首先介紹一篇很好的文章:Persisting Enums in JPA

一、列舉型別的基礎知識

public enum Status {
    OPEN, REVIEW, APPROVED, REJECTED;
}

1、列舉序號:

OPEN, REVIEW, APPROVED, REJECTED 列舉的序號從0開始依次遞增,本例中分別為0、1、2、3,可以通過Enum.ordinal()獲取;
缺點:
  • 可讀性,閱讀int型別的資料庫紀錄很困難;
  • 順序性,無法自定義序號(列舉序號從0遞增步進為1),在儲存某些行業的標準程式碼(如HTTP狀態碼)頗為不便;
  • 健壯性,如果錯誤地在中間插入或者重排序,會導致資料異常且不易發現;

優點:

  • 節省儲存空間

2、列舉字面值:

OPEN, REVIEW, APPROVED, REJECTED 列舉的字面值即為名稱本身,本例中分別為 OPEN、REVIEW、APPROVED、REJECTED,可以通過Enum.name()獲取;
缺點:
  • String型別,佔用空間更大,
  • 不支援數字,不支援重新命名,
  • 不推薦使用NON-ASCII字元,而很多情況下我們有儲存中文的需求;
  • 無法相容以“列舉序號”儲存的歷史專案;

優點:

  • 可以通過@Enumerated(EnumType.STRING)比較方便地進行轉化處理

3、列舉屬性值:

// 我們可以通過如下方法定義列舉的屬性值
public enum Gender {
    BOY(0, "boy", "Boy"),
    GIRL(1, "girl", "Girl");

    private int value;
    private String format1;
    private String format2;

    //....省略
}

缺點:

  • 列舉屬性值和列舉序號之間要保證區分度,防止混淆和儲存是發生錯誤操作;

優點:

  • 自由,靈活;

二、列舉的儲存

1、儲存列舉序號和列舉字面值的儲存

1.1 使用@Enumerated註解

  • 在儲存列舉時,JPA預設儲存 列舉序號
  • 在序列化列舉時,JPA預設顯示 列舉字面值
  • 可以通過@Enumerated註解切換列舉儲存時實際儲存的行為
    • @Enumerated(EnumType.ORDINAL) - 儲存序號
    • @Enumerated(EnumType.STRING) - 儲存字面值
  • 可以通過在列舉屬性上新增@JsonValue註解作為序列化的值;

1.2 使用@PostLoad和@PrePersist

不推薦,會使JPQL失效,還會增加@Transient欄位

2、儲存列舉屬性值

如果需要儲存列舉屬性值,可以使用@Converter註解

三、參考資料

1、JPA插入列舉型別欄位(介紹了列舉的序號/字面值/屬性)

2、Persisting Enums in JPA(介紹瞭如何使用@Enumerated、@PostLoad和@PrePersist、@Converter進行列舉的儲存)

3、解決JPA的列舉侷限性(介紹了實現中的一些問題)

相關文章