上一篇說到spring boot 使用jackson在枚舉enum序列化和反序列化的問題,
再來說說在JPA中實體entity使用枚舉的問題。
還是這個枚舉:
@Getter @AllArgsConstructor public enum EnumExpenseType implements BaseEnum { 小歡喜(1), 大歡喜(2); private final int value; }
當然,如果value值和枚舉的索引ordinal能夠對應上,就不用做任務配置了,這里的前提是沒有對應上。
無論是在實體的保存和查詢映射上還是有和jackson序列化同樣的問題,畢竟jpa是不知道我們的枚舉的構造函數是什么的,除非我們告訴它。
直接上代碼:
@Slf4j public class EnumConverter<E extends BaseEnum> implements AttributeConverter<E, Integer> { private final Class<E> clazz; public EnumConverter(Class<E> clazz) { this.clazz = clazz; } @Override public Integer convertToDatabaseColumn(BaseEnum attribute) { return attribute.getValue(); } @SuppressWarnings("unchecked") @Override public E convertToEntityAttribute(Integer dbData) { if (dbData == null) { return null; } E[] enumConstants = clazz.getEnumConstants(); for (E e : enumConstants) { if (e.getValue() == Integer.valueOf(dbData)) { return e; } } log.error("枚舉轉化異常。枚舉【" + clazz.getSimpleName() + "】,數據庫庫中的值為:【" + dbData + "】"); return null; } }
這里關鍵的兩個方法,一個是把枚舉的值保存到數據時,使用我們定義的value,而不是索引ordinal。
另一個是從數據庫中查詢字段映射枚舉時,按照value映射,而不是索引ordinal。
這只是一個抽象的方法,具體每個枚舉還是再寫一個類繼承這個類,就可以了。
如:
public class EnumExpenseTypeConverter extends EnumConverter<EnumExpenseType> { public EnumExpenseTypeConverter ()
{ super(EnumExpenseType.class); } }