首先介绍一篇很好的文章: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注解:JPA Attribute Converters
三、参考资料
1、JPA插入枚举类型字段(介绍了枚举的序号/字面值/属性)
2、Persisting Enums in JPA(介绍了如何使用@Enumerated、@PostLoad和@PrePersist、@Converter进行枚举的存储)
3、解决JPA的枚举局限性(介绍了实现中的一些问题)
4、JPA遇到枚举类型(JPA中涉及枚举的4种查询方法)