小编典典

使用固定值映射 JPA 中的枚举?

all

我正在寻找使用 JPA 映射枚举的不同方法。我特别想设置每个枚举条目的整数值并只保存整数值。

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {

  public enum Right {
      READ(100), WRITE(200), EDITOR (300);

      private int value;

      Right(int value) { this.value = value; }

      public int getValue() { return value; }
  };

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "AUTHORITY_ID")
  private Long id;

  // the enum to map : 
  private Right right;
}

一个简单的解决方案是将 Enumerated 注解与 EnumType.ORDINAL 一起使用:

@Column(name = "RIGHT")
@Enumerated(EnumType.ORDINAL)
private Right right;

但在这种情况下,JPA 映射枚举索引 (0,1,2) 而不是我想要的值 (100,200,300)。

我发现的两个解决方案似乎并不简单......

第一个解决方案

此处提出的解决方案使用@PrePersist
和@PostLoad 将枚举转换为其他字段并将枚举字段标记为瞬态:

@Basic
private int intValueForAnEnum;

@PrePersist
void populateDBFields() {
  intValueForAnEnum = right.getValue();
}

@PostLoad
void populateTransientFields() {
  right = Right.valueOf(intValueForAnEnum);
}

第二种解决方案

这里提出的第二种解决方案提出了一个通用的转换对象,但看起来仍然很重且面向休眠(@Type
在 Java EE 中似乎不存在):

@Type(
    type = "org.appfuse.tutorial.commons.hibernate.GenericEnumUserType",
    parameters = {
            @Parameter(
                name  = "enumClass",                      
                value = "Authority$Right"),
            @Parameter(
                name  = "identifierMethod",
                value = "toInt"),
            @Parameter(
                name  = "valueOfMethod",
                value = "fromInt")
            }
)

还有其他解决方案吗?

我有几个想法,但我不知道它们是否存在于 JPA 中:

  • 加载和保存权限对象时使用权限类右成员的setter和getter方法
  • 一个等效的想法是告诉 JPA Right enum 将 enum 转换为 int 并将 int 转换为 enum 的方法是什么
  • 因为我使用的是 Spring,有没有办法告诉 JPA 使用特定的转换器(RightEditor)?

阅读 72

收藏
2022-06-20

共1个答案

小编典典

对于早于 JPA 2.1 的版本,JPA 仅提供两种处理枚举的方法,通过它们的name或它们的ordinal. 并且标准 JPA
不支持自定义类型。所以:

  • 如果您想进行自定义类型转换,则必须使用提供程序扩展(使用 Hibernate UserType、 EclipseLinkConverter等)。(第二种解决方案)。〜或〜
  • 您必须使用 @PrePersist 和 @PostLoad 技巧(第一个解决方案)。〜或〜
  • 注释getter和setter取值和返回int值~or~
  • 在实体级别使用整数属性并在 getter 和 setter 中执行转换。

我将说明最新的选项(这是一个基本的实现,根据需要进行调整):

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {

    public enum Right {
        READ(100), WRITE(200), EDITOR (300);

        private int value;

        Right(int value) { this.value = value; }

        public int getValue() { return value; }

        public static Right parse(int id) {
            Right right = null; // Default
            for (Right item : Right.values()) {
                if (item.getValue()==id) {
                    right = item;
                    break;
                }
            }
            return right;
        }

    };

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "AUTHORITY_ID")
    private Long id;

    @Column(name = "RIGHT_ID")
    private int rightId;

    public Right getRight () {
        return Right.parse(this.rightId);
    }

    public void setRight(Right right) {
        this.rightId = right.getValue();
    }

}
2022-06-20