我正在寻找使用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一起使用.依次的:

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

但是在本例中,JPA映射枚举索引(0,1,2),而不是我想要的值(100,200,300).

我发现的这两个解决方案看起来并不简单.

第一个解决方案

解决方案proposed here使用@PrePersist和@PostLoad将枚举转换为其他字段,并将枚举字段标记为瞬态:

@Basic
private int intValueForAnEnum;

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

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

第二种解决方案

第二个解决方案proposed here提出了一个通用的转换对象,但是看起来仍然是沉重的、面向Hibernate的(@Type似乎不存在于JavaEE中):

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

还有其他解决方案吗?

我脑海中有几个 idea ,但我不知道它们是否存在于JPA中:

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

推荐答案

对于早于JPA2.1的版本,JPA只提供了两种处理枚举的方法,即按name或按ordinal处理枚举.并且标准JPA不支持自定义类型.因此:

  • 如果想进行自定义类型转换,就必须使用提供程序扩展(Hibernate UserType、EclipseLink Converter等).(第二种解决方案)~或者~
  • 你必须使用@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();
    }

}

Java相关问答推荐

如何专门保存数据而不显示在jTable中?

我们如何直接使用kerminldap服务票证来通过ldap进行身份验证并形成LDAP上下文

在FML中删除关键帧动画

Java自定义ThreadPool—暂停任务提交并取消当前排队任务

即使我正在使用并发方法,使用Javascript的应用程序也会继续冻结'

滚动视图&不能在alert 对话框中工作(&Q;&Q;)

呈现文本和四舍五入矩形时出现的JavaFX窗格白色瑕疵

由于我在Main方法中关闭了 scanner ,但在该方法中创建了一个新的 scanner ,因此出现了错误

为什么Java编译器不区分不同类型的方法?

在JDK 1.8源代码中,为什么使用A-B 0来确定哪个更大,而不是A B?

使用htmlunit和java单击按钮

如何使用Criteria Builder处理一对多关系中的空值?

找出承载Cargo 的最小成本

Java嵌套流查找任意值

如何对存储为字符串的大数字数组进行排序?

接受类及其接口的Java类型(矛盾)

H2数据库仅支持%1个结果集?

我们可以在方法中声明接口吗?

Cucumber java-maven-示例表-未定义一步

如何使用stream.allMatch()为空流返回false?