How to implement a JPA Attribute Converter

JPA 2.1 brings several improvements. One of them is the Attribute 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<Color, String> {

 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 Attribute Converter.

Looking for more information? Take a look at some of my best tutorials or have a look at the other examples on how to use an Attribute Converter:

Related Articles

Responses

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

  1. Hi Thorben,

    Very helpful article – thank you!

    It seems that a converter is only used when reading an entity from a database, not writing an entity to a database. Is that correct?

    1. Hi Chris,
      the converter is used in both directions. The convertToDatabaseColumn is called during write operations to convert entity attribute’s values and for query parameters. The convertToEntityAttribute is used when reading entity attribute’s values from the database.

  2. Hi Thorben.

    You already wrote about the exceptions concerning converting an id Attribute. Are there workarounds or official ways
    to Convert e.g. an String to an UUID vice versa?
    We had to switch our underlaying database from postgres to db/2, which does not support UUIDs natively. So we have to convert these right now.

    Kind regards

  3. This helped me.

    Thank-you

  4. Nice tut man!

  5. Will AttributeConverter will get invoked in case of
    1. Static(Named) Or Dynamic Queries using javax.persistence.Query interface and entiyManager
    2. Queries using javax.persistence.Query interface and entiyManager with POJO (Constructor) used to map query result.

    1. Hi Amit,

      yes the AttributeConverter gets applied in all these situations.
      The only situation in which it isn’t used is a native SQL query.

      Regards,
      Thorben

      1. Great

        Thanks …

  6. Saved my day

  7. that’s great (Y)

  8. Hi, I see X and Y values. You mentioned them as well but you never used them in code. Are them optional?

    1. The X and Y were mentioned in the reference to the AttributeConverter interface:

      A Converter must implement the javax.persistence.AttributeConverter 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.

  9. Is there any reason why ID attributes can not be converted?
    Hibernate User Types can be used with IDs, though.

    1. Hi Stefan,

      that’s the way it’s defined in the JPA spec. To be honest, I don’t know why they excluded IDs. One reason might be, that the conversion has to be biuniquely and that there is no way the spec or persistence provider can assure that.

      Regards,
      Thorben

  10. Its not working even after changing hibernate-jpa 2.0 module of Jboss to hibernate-jpa-2.1-api-1.0.0.Final.jar… any idea? why its not being called?

    1. Hi Raghu,
      you need to update the used Hibernate module to a version >4.3.0 or switch to Wildfly 8. The hibernate-jpa-2.1-api-1.0.0.Final.jar provides only the JPA 2.1 APIs but not the implementation.
      Regards,
      Thorben

  11. I followed the same steps as above..
    But my Converter never being called.
    I am using hibernate-jpa-2.1-api-1.0.0.Final.jar
    on Jboss 7.1.1 server…

    PLs help me

  12. Hi,

    It's possible to convert an object into more than one column, with converters?

  13. Hi Thorben and others,

    I have a project where I need to create many different (70+) enums and hence repeatedly define 70+ AttributeConverters. Even though using Java8, there is no neat way of doing things at compile time.

    Anyone knows if we could define those converters at runtime?

    Karyn

  14. I see it's very similar to FacesConverter 🙂

  15. While conversion between entity type and JDBC type is useful for 90% of all use-cases, it is not useful for special cases where the database type is a non-standard type, like PostgreSQL's JSON type, for instance.

    In jOOQ 3.5, we've introduced a new binding SPI, which helps users interact with JDBC bind values on a JDBC level. I wonder if such a thing is possible in JPA as well?

  16. Is there also a way to use the Converter implicitly with a javax.persistence.Query? When I add the Object as a query parameter then I get an Exception.

  17. 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

Black Friday & Launch Offer: Join the Persistence Hub!

Hi and welcome!

To make sure I provide you with the best content, please tell me what you are looking for.