Saturday, November 20, 2010

JPA - @Enumerated default attribute

Sometimes you have to store Java Enum value into database, using JPA. As we all know it is pretty simple in fact, using @Enumerated annotation, like in the example below:
public enum BenefitType { 
    GROUP_TERM_LIFE, HEALTH_COVERAGE, LEGAL_ASSISTANCE, RETIREMENT_PLAN, TRANSPORTATION
}

public class Benefit implements Serializable {
    ...
    private BenefitType type;
    ...
    @Column(name = "BENEFIT_TYPE")
    @Enumerated
    public BenefitType getType() {
        return type;
    }
    ...
}
Yes, pretty simple, but also pretty perfidious :). Why? Because developers very often use the default values for annotation attributes, and @Enumerated attribute named value is by default EnumType.ORDINAL.

Good Lord! This means that JPA provider will use the Enum's ordinal method result as the value stored into database! Exactly, my dear Watson ... I believe you know, what it means ... one day, when some of the developers will add a new Enum value to the list of previously defined, or even sort the existing values, and thus change their order, the ordinal method may return completely different value than expected!

Whoever was the creator of @Enumerated annotation he/she didn't read the Enum's ordinal method JavaDoc, where we can find clear declaration:Most programmers will have no use for this method. It is designed for use by sophisticated enum-based data structures, such as EnumSet and EnumMap.

My conclusion is:
  • Do not add to your API anything which can cause unpredictable behavior of the code, and thus is useless in real world
  • Do not make such a thing the default value for anything - there will be hundreds of people who will use the default value
  • Read the documentation for the code used by you, repeatedly, as long as you understand it 

2 comments:

  1. Yeah, I always make sure to set it to EnumType.STRING to avoid this.

    ReplyDelete
  2. Exactly! Probably most of us do it, those who don't will suffer sooner or later ;) And that's the case, where wrong assumption at the creation of some API requires special care from the Developers using it ... :(

    ReplyDelete