枚举类型在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的枚举局限性(介绍了实现中的一些问题)