The ordinal of an Enum is used together with JPA to set the database value of an Enum type field of an entity. Since i find the use of the ordinal dangerous in case of future changes i was searching for an alternative way of populating my database field while still using the Enum in my application code.
The first obvious solution might be using the EnumType.STRING option of the @Enumerated annotation. In my opinion this could be usable when the database can be refactored to hold those string representations.
The case i ran into was a defined database field of NUMBER called status with the possible values of 0,100 and 200 meaning INITIAL, ACTIVE and INACTIVE. Using the default conversion with the below mentioned enum would mean that the values 0, 1 and 2 where used to insert into the database.
public enum Status {
INITIAL, ACTIVE, INACTIVE;
}
and using the enum in the entity class
private Status status
And what if someone decides to add an extra status called CHECKED with a value of 10?
Should i create an Enum like this to be able to use the default?
public enum Status {
INITIAL, UNUSED_1, …, UNUSED_9, CHECKED, UNUSED_11 .. UNUSED_99, ACTIVE, DO_YOU_GET_THE_FEELING?;
}
So i looked further and found that with EclipseLink (the JPA provider we use) it’s possible to define a Converter and use that in your Entities. So let’s try.
First we need an Enum which contains the correct value inside: (See also a previous blog on Enums)
public enum Status {
INITIAL(0), CHECKED(10), ACTIVE(100), INACTIVE(200);
private final byte status;
private Status(int value) {
status = (byte) value;
}
public int getValue() {
return status;
}
}
Next we need a Converter:
public class StatusEnumConverter implements Converter {
public Object convertDataValueToObjectValue(Object data, Session session) {
//TODO implement converting database value to Enum
return null;
}
public Object convertObjectValueToDataValue(Object data, Session session) {
if (data instanceof Status) {
return BigDecimal.valueOf(((Status) data).getValue());
}
return null;
}
public void initialize(DatabaseMapping dbMap, Session session) {
// No need for database mapping
}
public boolean isMutable() {
return false;
}
}
That’s one way traffic now. How do we get form a value to the correct item of the enum?
Looking on the internet i found the Enum Inversion problem which supplied me with a solution for this. Also i wanted the StatusEnumConverter to be more generic so the converter could be easily reused. I create a ReverseEnumMap class to aid to the problem of getting the right Enum value and a convertable interface to generify (is that a word?) the Converter. The end result looks like this:
public class ReverseEnumMap & Convertable> {
private Map
And this is how you will use the converter in your entity class. Annotating the status field. Note that you only have to define the @Converter annotation once to be able to use the @Convert in other entities also!
@Converter(name="status", converterClass=com.xebia.enum.converters.StatusConverter.class)
@Convert("status")
private Status status;
So with this i think we have a pretty generic solution to avoid using ordinal with enums and JPA.

Comments (4)
Anthony -
December 24, 2009 at 3:32 am
Do you have the full code for this? I’m a bit confused with the use of Status.NOT_YET_ACTIVE which has not been defined in your Enum.
I’m trying a similar approach but when getConvertableEnum is called, is the value of the Enum relevant?
Kris -
December 28, 2009 at 9:11 am
Hi Anthony,
The method getConvertableEnum is just a way to specify a default value of the Enum to return when there is no data in the database column. So i used NOT_ACTIVE_YET as the default.
I agree it’s a bit confusing that this Enum value is not mentioned earlier. So i will change it into return Status.INITIAL for clarity.
Kris
Bhaskar -
January 30, 2012 at 7:06 am
How sorting will be working with this implementation??
Kris Geusebroek -
January 30, 2012 at 9:55 am
Hi Bhaskar,
In java there are two way to sort some object, the first is to implement the Comparable interface. This is already done with the Enum class. Only bad thing about this is that the compareTo method is declared final so you cannot change the default way of sorting.
The second option you have is to write a Comparator.
something like:
class StatusComparator implements Comparator
{
public int compare(Status o1, Status o2)
{
return o1.getValue() – o2.getValue();
}
}