About Thorben Janssen

Thorben Janssen is a senior developer with more than 10 years of experience in Java EE development and architecture. During these years he acted as developer, architect, project and/or technical lead to create high available, clustered mobile billing solutions and laboratory information management systems.

JPA 2.1 Type Converter – The better way to persist enums

Persisting enums with JPA 2.0 is possible, but there is no nice way to do it. Using the @Enumerated annotation, you can use EnumType.ORDINAL or EnumType.STRING to map the enum value to its database representation. But both options have some drawbacks, that we will discuss in the first part of this article. In the second part, I will show you to avoid these drawbacks by using a JPA 2.1 Type Converter.

Persisting enums with JPA 2.0

EnumType.ORDINAL uses the return value of Enum.ordinal() to persist the enum. So the first value of the enum will be mapped to 0, the second to 1 and so on. While this looks compact and easy to use in the first place, it causes problems when changing the enum. Removing enum values or adding a new value somewhere in between will change the mapping of all following values, e.g.:

before:

Vehicle:
CAR     -> 0
TRAIN   -> 1
PLANE   -> 2

after:

Vehicle:
CAR     -> 0
BUS     -> 1
TRAIN   -> 2
PLANE   -> 3

Adding Bus at the second position would require a database update to fix the enum mapping.

EnumType.STRING looks like a better option. It uses the String representation of the enum to persist it in the database. So adding or removing values will not change the mapping. But this representation can be quite verbose and renaming an enum value will break the mapping.

before: 

Vehicle:
CAR     -> CAR
TRAIN   -> TRAIN
PLANE   -> PLANE

after:

Vehicle:
CAR     -> CAR
BUS     -> BUS
TRAIN   -> TRAIN
PLANE   -> PLANE

Using JPA 2.1 Type Converter

JPA 2.1 Type Converter provide a third and in my opinion the best option. A Type Converter allows us to implement methods to convert the value of an entity attribute to its database representation and back. I will not get into too much details on how to implement a Type Converter because I already did this in one of my former articles.

By implementing our own mapping, we can choose a compact database representation and make sure, that changing the enum in any way will not break the existing mapping. The following example shows how to implement a type converter for the Vehicle enum:

@Converter(autoApply = true)
public class VehicleConverter implements AttributeConverter<Vehicle, String> {

 @Override
 public String convertToDatabaseColumn(Vehicle vehicle) {
  switch (vehicle) {
  case BUS:
   return "B";
  case CAR:
   return "C";
  case PLANE:
   return "P";
  case TRAIN:
   return "T";
  default:
   throw new IllegalArgumentException("Unknown value: " + vehicle);
  }
 }

 @Override
 public Vehicle convertToEntityAttribute(String dbData) {
  switch (dbData) {
  case "B":
   return Vehicle.BUS;
  case "C":
   return Vehicle.CAR;
  case "P":
   return Vehicle.PLANE;
  case "T":
   return Vehicle.TRAIN;
  default:
   throw new IllegalArgumentException("Unknown value: " + dbData);
  }
 }

}

The VehicleConverter maps the enum value to a one character String. By declaring it with @Converter(autoApply = true), we tell the JPA provider to use this Type Mapper to map all Vehicle enums. So we do not need to specify the converter at each entity attribute of type Vehicle.

But there is one thing we need to take care of and if you have read my former article about JPA Type Converter you might have wondered already. Type Converter cannot be applied to attributes annotated with @Enumerated. So we have to make sure that there is no @Enumerated annotation at our entity attributes of type Vehicle.

Conclusion

We implemented a simple Type Converter that uses our own rules to convert the Vehicle enum to its database representation. So we can make sure that changing the values of the Vehicle enum will not break the existing/remaining mappings.

Related Whitepaper:

Functional Programming in Java: Harnessing the Power of Java 8 Lambda Expressions

Get ready to program in a whole new way!

Functional Programming in Java will help you quickly get on top of the new, essential Java 8 language features and the functional style that will change and improve your code. This short, targeted book will help you make the paradigm shift from the old imperative way to a less error-prone, more elegant, and concise coding style that’s also a breeze to parallelize. You’ll explore the syntax and semantics of lambda expressions, method and constructor references, and functional interfaces. You’ll design and write applications better using the new standards in Java 8 and the JDK.

Get it Now!  

One Response to "JPA 2.1 Type Converter – The better way to persist enums"

Leave a Reply


− four = 1



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books