Tuesday, October 4, 2016

Examples of JPA attribute converters

Custom attribute conversion allows specify mapping between database and Java representation of an attribute. This may be done by implementing the JPA interface AttributeConverter. This post shows two examples of conversion:
1. A boolean Java attribute into an integer in DB
2. A String Java attribute into encrypted String in DB

The AttributeConverter interface defines the following API: the method convertToDatabaseColumn should implement mapping from Java to DB representation; the method convertToEntityAttribute - DB to Java mapping.
The implementation class should be annotated with a @Converter annotation:
 @Converter 
 public class CustomConverter implements AttributeConverter<JavaType, DbType> { 
      @Override  
      public DbType convertToDatabaseColumn(JavaType attribute) {
          ...
      }  
      @Override  
      public JavaType convertToEntityAttribute(DbType dbData) {  
         ... 
      }  
 }
I read through several posts about JPA attribute converter implementation, which suggest explicit binding between attribute converter and a particular Java attribute. Some posts state, that a custom converter should be applied to an attribute by putting the @Convert annotation above the attribute or above its getter. Others suggest usage of an aggregated @Converts annotation above the class. I tried all the options, but desired conversion did not happen.

Apparently the following working solution was figured out: a converter should be implemented as auto-applied. In such a case all attributes of the type are converted automatically.
A converter is defined as auto-applied with a value autoApply=true:
 @Converter(autoApply = true)  
 public class CustomConverter implements AttributeConverter<JavaType, DbType> { 
     ... 
 }
To disable automatic conversion for a particular attribute the @Convert(disableConversion=true) annotation should be put above the attribute.

Example of Boolean attribute conversion


The example demonstrates a boolean attribute, which is stored in DB as an integer: false as 0 and true as 1.

DB schema:
 `HOST_REGISTERED` tinyint(1) NOT NULL DEFAULT 1,
JPA entity attribute:
 @Column(name="HOST_REGISTERED", nullable=false)
 private boolean hostRegistered;
Attribute converter implementation:
 @Converter(autoApply = true)  
 public class DbBooleanConverter implements AttributeConverter<Boolean, Integer> {  
      @Override  
      public Integer convertToDatabaseColumn(Boolean attribute) {  
           if (Boolean.TRUE.equals(attribute)){  
                return 1;  
           }  
           else {  
                return 0;  
           }  
      }  
      @Override  
      public Boolean convertToEntityAttribute(Integer dbData) {  
           if (dbData == null) {  
                return Boolean.FALSE;  
           }  
           else {  
                return (dbData == 0) ? Boolean.FALSE : Boolean.TRUE;  
           }  
      }  
 }  

Example of String encryption conversion


The example demonstrates a String attribute, which is stored in DB as an encrypted string. Such converter may be used for storing of a password in DB.

DB schema:
 `PASSWORD` varchar(256) NOT NULL,
JPA entity attribute:
 @Column(name="PASSWORD", nullable=false)
 private Password password;
Attribute converter implementation uses for convertion the class PasswordCryptor, which is not shown here:
 @Converter(autoApply = true)  
 public class DbPasswordConverter implements AttributeConverter {
      public static PasswordCryptor PASSWORD_CRYPTOR = new PasswordCryptor(); 
      @Override
      public String convertToDatabaseColumn(Password attribute) {
            return PASSWORD_CRYPTOR.encrypt(attribute.getValue());
      } 
      @Override
      public Password convertToEntityAttribute(String dbData) {
            Password p = new Password();
            p.setValue(PASSWORD_CRYPTOR.restore(dbData));
            return p;
      } 
 }

No comments :

About the author

My Photo
I trust only simple code and believe that code should be handsome. This is not a matter of technology, but professional approach, consolidated after years of software development. I enjoy to cause things working and feel very happy, when I manage to solve a problem.
Back to Top