JPA 2.1 - How to implement a Type Converter

JPA 2.1 brings several improvements. One of them is the Type Converter. It allows the developer to specify methods to convert between the database and the java representation of an attribute.


What can be converted?

A Converter supports type conversion of all basic attributes defined by entity classes, mapped superclasses, or embeddable classes. The only exceptions are Id attributes, version attributes, relationship attributes and attributes annotated as Temporal or Enumerated.

How to implement a Converter?

A Converter must implement the javax.persistence.AttributeConverter<X, Y> interface, where X is the class of the entity representation and Y the class of the database representation of the attribute. Additionally a Converter has to be annotated with the javax.persistence.Converter annotation.
The following example shows a Converter implementation that can be used to store a java.awt.Color object as a String with the format red|green|blue|alpha in the database. When reading the entity from the database, the String will be used to instantiate a new Color object.
package blog.thoughts.on.java.jpa21.converter;

import java.awt.Color;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter
public class ColorConverter implements AttributeConverter {

 private static final String SEPARATOR = "|";

 /**
  * Convert Color object to a String 
  * with format red|green|blue|alpha
  */
 @Override
 public String convertToDatabaseColumn(Color color) {
  StringBuilder sb = new StringBuilder();
  sb.append(color.getRed()).append(SEPARATOR)
     .append(color.getGreen())
     .append(SEPARATOR)
     .append(color.getBlue())
     .append(SEPARATOR)
     .append(color.getAlpha());
  return sb.toString();
 }

 /**
  * Convert a String with format red|green|blue|alpha
  * to a Color object
  */
 @Override
 public Color convertToEntityAttribute(String colorString) {
  String[] rgb = colorString.split(SEPARATOR);
  return new Color(Integer.parseInt(rgb[0]), 
      Integer.parseInt(rgb[1]),
      Integer.parseInt(rgb[2]), 
      Integer.parseInt(rgb[3]));
 }

}

As you can see the implementation is simple and straight forward. You just need to implement one method for each conversion.

How to use a Converter?

There are two options to define the usage of a Converter. The first one is to set autoapply=true at the @Converter annotation of the Converter class. In this case the JPA provider will use this Converter to convert all entity attributes of the given type.
If autoapply is set to false, you need to add the javax.persistence.Convert annotation to all attributes that shall be converted and specify the Converter class. The following code snippet shows an example for this approach:
@Entity
public class RectangleEntity
{

   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Integer id;

   @Column
   private Integer x;

   @Column
   private Integer y;

   @Column
   @Convert(converter = ColorConverter.class)
   private Color color;

   ...
}

That is all that needs to be done to implement a simple Type Converter. Check the specification or the Java Doc for more advanced conversion features.
If you want to try it yourself, you can use Hibernate 4.3.0.Beta4 which is part of the new Wildfly 8.0.0.Beta1 release.

Do you have any ideas or questions about using JPA Converters, please leave a comment.
If you enjoyed reading this article and like to learn more about other Java EE7 features, make sure to subscribe to my RSS feed or follow me on twitter or google+.

Links

JPA 2.1 Specification
Java Doc javax.persistence

2 comments:

  1. Hi

    Thanks for the article.

    I am using JBoss AS 7.1. I set the "" in persistence.xml. But it looks like the converer is not getting called in my case. Could you please help for the same. If the request comes from tomcat, then the converter is being called but not if the request is from jboss.

    Your help would be highly appreciable

    Thanks

    ReplyDelete
    Replies
    1. Hi,

      JBoss AS 7.1 supports only JPA 2.0, but type converter are new with JPA 2.1. You need to use Wildfly instead.
      Or have a look at hibernate custom types, if you need to stay with JBoss AS 7.1: http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html_single/#types-custom

      Regards,
      Thorben

      Delete