如何在JPA中映射具有固定值的枚举?

6 浏览
0 Comments

如何在JPA中映射具有固定值的枚举?

我正在寻找使用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;
}

一个简单的解决方案是使用具有EnumType.ORDINAL的Enumerated注释:

@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);
}

第二个解决方案

第二个解决方案提出了一个通用的转换对象,但仍然显得笨重,而且是面向Hibernate的(Java EE中貌似不存在@Type):

@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中:

  • 在加载和保存Authority对象时使用Authority类的正确成员的setter和getter方法
  • 一个等效的想法是告诉JPA Right枚举的方法,将枚举转换为int和int转换为枚举
  • 因为我使用Spring,有没有办法告诉JPA使用特定的转换器(RightEditor)?
admin 更改状态以发布 2023年5月23日
0
0 Comments

现在使用JPA 2.1可以实现:

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

更多细节:

0
0 Comments

在JPA 2.1之前的版本中,JPA仅提供通过枚举的nameordinal处理枚举的两种方法,并且标准的JPA不支持自定义类型。所以:

  • 如果您想进行自定义类型转换,则必须使用提供程序扩展(使用Hibernate的UserType,EclipseLink的Converter等)(第二种解决方案)。或者
  • 您必须使用@PrePersist和@PostLoad技巧(第一种解决方案)。或者
  • 在getter和setter上使用注释,以获取并返回int值。或者
  • 在实体级别使用整数属性,并在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();
    }
}

0