Map enum in JPA with fixed values? Map enum in JPA with fixed values? java java

Map enum in JPA with fixed values?


For versions earlier than JPA 2.1, JPA provides only two ways to deal with enums, by their name or by their ordinal. And the standard JPA doesn't support custom types. So:

  • If you want to do custom type conversions, you'll have to use a provider extension (with Hibernate UserType, EclipseLink Converter, etc). (the second solution). ~or~
  • You'll have to use the @PrePersist and @PostLoad trick (the first solution). ~or~
  • Annotate getter and setter taking and returning the int value ~or~
  • Use an integer attribute at the entity level and perform a translation in getters and setters.

I'll illustrate the latest option (this is a basic implementation, tweak it as required):

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


This is now possible with JPA 2.1:

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

Further details:


From JPA 2.1 you can use AttributeConverter.

Create an enumerated class like so:

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

And create a converter like this:

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

On the entity you just need:

@Column(name = "node_type_code")

You luck with @Converter(autoApply = true) may vary by container but tested to work on Wildfly 8.1.0. If it doesn't work you can add @Convert(converter = NodeTypeConverter.class) on the entity class column.