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