All JPA implementations, including Hibernate, provide default mappings for a large set of standard Java classes. Through these mappings it is possible to model the attributes of an entity and map a table.
But sometimes this is not possible, for this reason in this article we’ll see how to implement an AttributeConverter with JPA.
Diagram
Our application uses the following table called country which has two properties, name and code. The latter serves to identify a country and is unique.
Now let’s proceed with the mapping by creating the following classes:
@Entity @Table(name = "country") public class Country { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; private String name; private CountryCode code; // getters and setters }
public enum CountryCode { ITALY("ita"); private String value; // constructor and getter }
The Country entity uses an enumerate to save the code. Now we need a converter that transforms CountryCode into a database column and vice versa. In our case we will save the value property of CountryCode in the database and instead when we read we will convert the string into CountryCode.
To do this we need a converter and fortunately JPA provides us with an interface called AttributeConverter to implement.
Implementing an AttributeConverter
The JPA AttributeConverter is a great solution when you need to convert a particular Java type into a database column. Now let’s create our converter:
public class CountryCodeAttributeConverter implements AttributeConverter<CountryCode, String> { @Override public String convertToDatabaseColumn(CountryCode attribute) { return attribute.getValue(); } @Override public CountryCode convertToEntityAttribute(String dbData) { return CountryCode.valueOf(dbData); } }
The implementation of the AttributeConverter is pretty simple. The interface defines the methods convertToDatabaseColumn and convertToEntityAttribute. The JPA provider call these methods to either convert the value of your entity attribute to the type handled by the JDBC driver or vice versa.
Mapping the AttributeConverter
To inform JPA that we want to use a particular converter, we need to add the @Convert annotation on the attribute to be transformed. This is the classic approach if you intend to use the converter only in one entity.
@Convert(converter = CountryCodeAttributeConverter.class) private CountryCode code;
Auto-registering the AttributeConverter
If you have multiple entities that use the same Java type that you set in the AttributeConverter, you can automatically register the converter by adding the @Converter annotation on the AttributeConverter implementation.
@Converter(autoApply = true) public class CountryCodeAttributeConverter implements AttributeConverter<CountryCode, String> { //.. }
Using the AttributeConverter
Now that we have everything set up it’s time to try out our converter, let’s try inserting a Country:
EntityManagerFactory emFactory = Persistence.createEntityManagerFactory("default"); EntityManager em = emFactory.createEntityManager(); em.getTransaction().begin(); Country country = new Country(); country.setName("Italy"); country.setCode(CountryCode.ITALY); em.persist(country); em.getTransaction().commit(); em.close(); emFactory.close();
For this project I used Hibernate as JPA implementation, below you’ll see the SQL it generated:
insert into country (id, code, name) values (default, 'ita', 'Italy')
Conclusion
In this article we have seen how you can implement an AttributeConverter with JPA. It provides an easy and portable way to define a custom mapping. You can use it for any attributes you want to map to a database column.
Source code is available on GitHub.