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
, EclipseLinkConverter
, 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.