[JPA_SPEC-47] Usability of @Enumerated and @MapKeyEnumerated Created: 11/Feb/13  Updated: 24/Nov/15

Status: Open
Project: jpa-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: jd3714att Assignee: ldemichiel
Resolution: Unresolved Votes: 8
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: enum, jpa


In mapping a pre-existing schema, it is rarely possible to map a given set of constants using an @Enumerated:

  • Ordinals are non-sequential
  • Names are incompatible with Java Enum Constants
  • Names cannot be aliased to something more useful or conventional for Java Naming standards

Limitation is because specification states the name() will be used of an enum.
A typical example: Database uses 'N/A', which can never be mapped to an enum. Intuition will let us look for a solution to map this to 'NOT_AVAILABLE', both a valid name for an Enum Constant, and also conventional naming.

On top of this, an enum often has a representation in the Database, and a constant has usually other additional attributes that could be useful.
Better than using the name() of an @Enumerated, we should map the enumerated similar as an @Entity, and use the @ID.

Comment by jd3714att [ 26/Nov/14 ]

Would this not be more elegant than using a @Converter to solve the problem.

public enum Language {
  private String code;
  private String description;

  Language(String code) {
    this.code = code;
  public String getCode() {
    return code;

  public String getDescription() {
    return description;
Comment by HajoLemcke [ 16/Dec/14 ]

This looks great. And it would solve the problem to have a separate converter for each enumeration because a generic converter can not be build type save.

Comment by rbygrave [ 28/Apr/15 ]

I don't think @Column(name="DESCRIPTION") is required. The only requirement is to mark the field (as you have done with @ID) or mark a getter method that returns the value to be stored in the DB.

So instead annotate the getCode() method like:

public String getCode() { return code; }


public String getCode() { return code; }

Another alternative would be to create an annotation that acts just like @XmlEnumValue does for xml mapping ... so create a @DbEnumValue such that:

public enum Language {


Comment by pbenedict [ 23/Nov/15 ]

This kind of custom transformation can now be expressed with Converters. I've done it myself for several situations. Converters, not enums that transform themselves into a DB value, is the correct way to separate out model code from integration code.

Comment by rbygrave [ 23/Nov/15 ]

> Converters, not enums that transform ...
For me I'd say its a balance between pragmatism and 'purity'. The @DbValue annotation on a method approach mirrors a similar approach Jackson takes for JSON and personally I think it represents significantly less work than writing a Converter. So yes, I'll agree to disagree with you there on pragmatism over purity grounds.

Comment by pbenedict [ 23/Nov/15 ]

Yes, it is less work. The approach you mention I have used for many years; finally turned away from it for several reasons. It began to breakdown the moment I had many ways of encoding an Enum for multiple systems: perhaps an existing database requires code XYZ but a new technology requires code ABC. All those things are possible which is why I think the "purity" aspect (integration code) is a better design because it frees you up from coupling concerns.

Comment by pbenedict [ 23/Nov/15 ]

In closing, I should mention that you could create a nearly-universal Enum-to-String attribute converter that accomplishes your reusability requirements. You already have the value in your example code; just move it into the enum constructor; provide a standard interface that exposes the code; finally do the conversion in the Converter.


public interface Coded {
  String code();

public enum Language implements Coded {

  private String code;

  private Language(String code) {
      this.code = code;

  // To database: converter uses this
  // From database: converter loops values() and compares DB column against code()  
  public String code() { return code; }

// Reusable universal logic to convert back and forth
public abstract class YourAbstractCodedConverter<X extends Enum<X> & Coded> implements AttributeConverter<X,String> { 

// Strongly typed for JPA
public class YourLocaleCodedConverter extends YourAbstractCodedConverter<Language> {
  // empty
Comment by pbenedict [ 24/Nov/15 ]

@rbygrave, I reverse my opinion. I went to demonstrate one thing and have concluded another. After writing out the code above, it's clear the code is boilerplate and more complex than is necessary. Thus, I now support this ticket and have voted it up. This should be allowed via an annotation.

The pattern above clearly keeps out the integration (JPA) from the model code. This is very important when the Enum is part of a public API (where no such dependency should be required), but this is not always everyone's goal. Sometimes Enums are dedicated to JPA ... or, as you said, you don't prefer to keep such a "pure" separation of concerns.

Comment by jd3714att [ 24/Nov/15 ]

@pbenedict, in regards to "pure" separation of concerns, who says that separation is not there? We only have Java Identifier (the enum instances) vs Internal Code, which neither has to be the actual vendor specific backing presentation. That separation should still be possible, although this is not what I intended. So to that regards I would also avoid using names that include "Xml", or "Db".

Generated at Fri Nov 27 02:43:31 UTC 2015 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.