上一篇说到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); } }