枚舉類型在JPA中的使用

首先介紹一篇很好的文章: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的枚舉局限性(介紹了實現中的一些問題)