首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在JPA中使用固定值映射枚举?

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

Stack Overflow用户
提问于 2010-05-02 06:14:59
回答 8查看 158.9K关注 0票数 214

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

代码语言:javascript
复制
@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一起使用:

代码语言:javascript
复制
@Column(name = "RIGHT")
@Enumerated(EnumType.ORDINAL)
private Right right;

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

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

第一个解决方案

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

代码语言:javascript
复制
@Basic
private int intValueForAnEnum;

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

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

第二种解决方案

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

代码语言:javascript
复制
@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哪些权限枚举的方法可以将枚举转换为int,将int转换为枚举
  • 因为我使用的是Spring,有没有什么方法可以告诉JPA使用特定的转换器(RightEditor) ?
EN

回答 8

Stack Overflow用户

回答已采纳

发布于 2010-05-02 07:25:57

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

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

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

代码语言:javascript
复制
@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();
    }

}
票数 180
EN

Stack Overflow用户

发布于 2014-01-12 17:52:57

现在使用JPA 2.1可以做到这一点:

代码语言:javascript
复制
@Column(name = "RIGHT")
@Enumerated(EnumType.STRING)
private Right right;

更多详细信息:

票数 86
EN

Stack Overflow用户

发布于 2014-08-11 23:32:57

在JPA2.1中,您可以使用AttributeConverter

创建一个枚举类,如下所示:

代码语言:javascript
复制
public enum NodeType {

    ROOT("root-node"),
    BRANCH("branch-node"),
    LEAF("leaf-node");

    private final String code;

    private NodeType(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }
}

创建一个转换器,如下所示:

代码语言:javascript
复制
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter(autoApply = true)
public class NodeTypeConverter implements AttributeConverter<NodeType, String> {

    @Override
    public String convertToDatabaseColumn(NodeType nodeType) {
        return nodeType.getCode();
    }

    @Override
    public NodeType convertToEntityAttribute(String dbData) {
        for (NodeType nodeType : NodeType.values()) {
            if (nodeType.getCode().equals(dbData)) {
                return nodeType;
            }
        }

        throw new IllegalArgumentException("Unknown database value:" + dbData);
    }
}

在您只需要的实体上:

代码语言:javascript
复制
@Column(name = "node_type_code")

您使用@Converter(autoApply = true)的运气可能因容器而异,但经过测试可以在Wildfly 8.1.0上运行。如果它不起作用,您可以在实体类列中添加@Convert(converter = NodeTypeConverter.class)

票数 31
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2751733

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档