AttributeConverter introduced in JPA 2.1. This article demonstrates JPA/Hibernate AttributeConverter with an example.
What is JPA AttributeConverter? AttributeConverter
is an interface, a class that implements AttributeConverter
interface can be used to convert entity attribute state into database column representation and back again. In other words AttributeConverter can be used to map Java type to JDBC type to an entity.
Following image illustrates the mapping between a Name custom Java type to VARCHAR type in database.
1. How to use AttributeConverter?
1.1. AttributeConverter
has following methods and the class which implements this interface should provide implementation for the methods.
Y convertToDatabaseColumn(X attribute)
– Converts the value stored in the entity attribute into the data representation to be stored in the database.X convertToEntityAttribute(Y dbData)
– Converts the data stored in the database column into the value to be stored in the entity attribute.
1.2. Following are the steps to use AttributeConverter
.
- Create a class that should implement
AttributeConverter
interface. - Use
@Convert
annotation to use the class created in step 1.
Following example demonstrates the how to use AttributeConverter
.
2. JPA AttributeConverter Example
2.1. Following is the Name
java class to represent User
full name. name = first name + last name
.
public class Name { private String fisrtName; private String lastName; // setters and getters }
2.2. Creating Attribute converter for the Name java type. Following class shows you how to create Attribute converter class.
@Converter(autoApply = true) public class NameAttributeConveter implements AttributeConverter<Name, String>{ @Override public String convertToDatabaseColumn(Name attribute) { String fname = attribute.getFisrtName() == null ? "anonymous" : attribute.getFisrtName(); String lname = attribute.getLastName() == null ? "" : attribute.getLastName(); return fname+" "+lname; } @Override public Name convertToEntityAttribute(String dbData) { if(dbData!=null && dbData.split(" ").length > 0) { Name name = new Name(); name.setFisrtName(dbData.split(" ")[0]); name.setLastName(dbData.split(" ")[1]); return name; } return null; } }
2.3. Using NameAttributeConveter
to map Name
field in User
entity.
@Entity(name = "USER") public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO, generator = "native") @GenericGenerator(name = "native", strategy = "native") @Column(name = "ID") private Long id; @Column(name = "USER_NAME") private String userName; @Column(name = "PASSWORD") private String password; @Convert(converter = NameAttributeConveter.class) @Column private Name name; // Other fields mapping and setters getters }
2.4. While implementing if you set autoApply = true
to the annotation @Converter
, you no need to use @Convert
annotation explicitly on the attributes. The default value for autoApply
is false
.
2.5. Testing the mapping. Following code is to test the mapping.
public class App { public static void main( String[] args ) { EntityManagerFactory emf = null; EntityManager entityManager = null; EntityTransaction transaction = null; try{ emf = Persistence.createEntityManagerFactory("jbd-pu"); entityManager = emf.createEntityManager(); transaction = entityManager.getTransaction(); transaction.begin(); User user = new User(); user.setUserName("mike"); user.setPassword("password"); Name name = new Name(); name.setFisrtName("Mike"); name.setLastName("Chan"); user.setName(name); // Setting Current Date user.setCreationTime(new Date()); user.setDateofBirth(new Date()); user.setUserType(UserType.EMPLOYEE); entityManager.persist(user); transaction.commit(); }catch(Exception e){ transaction.rollback(); e.printStackTrace(); }finally{ entityManager.close(); emf.close(); } } }
2.6. Database Results
3. Conclusion
In this article we have covered Jpa 2.1 AttributeConverter with an example.