Close

Auto applying conversion based on the target attribute type

[Updated: Mar 1, 2018, Created: Mar 1, 2018]

The Converter annotation has an element autoApply. If the value of this element is set to true (default is false), the converter will be applied to all attributes of the target 'type', including to basic attribute values that are contained within other, more complex attribute types. In this case we don't have to use @Convert annotation explicitly on the attributes.

Example

The Converter

@Converter(autoApply = true)
public class FileConverter implements AttributeConverter<File, String> {

  @Override
  public String convertToDatabaseColumn(File attribute) {
      return attribute.getAbsolutePath();
  }

  @Override
  public File convertToEntityAttribute(String dbData) {
      return new File(dbData);
  }
}

The Entity

@Entity
public class Journal {
  @Id
  @GeneratedValue
  private long id;
  @ElementCollection
  private Map<String, Report> reportMap;
    .............
  public void addReport(String reportName, String description, File file) {
      if (reportMap == null) {
          reportMap = new HashMap<>();
      }
      Report report = new Report();
      report.setDescription(description);
      report.setFile(file);
      reportMap.put(reportName, report);
  }
    .............
}
@Embeddable
public class Report {
  private String description;
  private File file;
    .............
}

The main class

public class ExampleMain {
  private static EntityManagerFactory entityManagerFactory =
          Persistence.createEntityManagerFactory("example-unit");

  public static void main(String[] args) {
      try {
          nativeQuery("Show Columns from Journal");
          nativeQuery("Show Columns from Journal_ReportMap");
          persistEntity();
          nativeQuery("Select * from Journal");
          nativeQuery("Select * from Journal_ReportMap");
          loadEntity();
      } finally {
          entityManagerFactory.close();
      }
  }

  public static void persistEntity() {
      Journal journal = new Journal();
      journal.addReport("name1", "test report 1", new File("c:/temp/report-1.txt"));
      journal.addReport("name2", "test report 2", new File("c:/temp/report-2.txt"));
      System.out.println("Persisting journal: " + journal);
      EntityManager em = entityManagerFactory.createEntityManager();
      em.getTransaction().begin();
      em.persist(journal);
      em.getTransaction().commit();
      em.close();
  }

  private static void loadEntity() {
      EntityManager em = entityManagerFactory.createEntityManager();
      Journal journal = em.find(Journal.class, 1L);
      System.out.println("Journal loaded: " + journal);
      em.close();
  }

  public static void nativeQuery(String s) {
      EntityManager em = entityManagerFactory.createEntityManager();
      System.out.printf("'%s'%n", s);
      Query query = em.createNativeQuery(s);
      List list = query.getResultList();
      for (Object o : list) {
          if (o instanceof Object[]) {
              System.out.println(Arrays.toString((Object[]) o));
          } else {
              System.out.println(o);
          }
      }
      em.close();
  }
}
'Show Columns from Journal'
[ID, BIGINT(19), NO, PRI, NULL]
'Show Columns from Journal_ReportMap'
[JOURNAL_ID, BIGINT(19), NO, PRI, NULL]
[DESCRIPTION, VARCHAR(255), YES, , NULL]
[FILE, VARCHAR(255), YES, , NULL]
[REPORTMAP_KEY, VARCHAR(255), NO, PRI, NULL]
Persisting journal: Journal{id=0, reportMap={name2=Report{, description='test report 2', file=c:\temp\report-2.txt}, name1=Report{, description='test report 1', file=c:\temp\report-1.txt}}}
'Select * from Journal'
1
'Select * from Journal_ReportMap'
[1, test report 2, c:\temp\report-2.txt, name2]
[1, test report 1, c:\temp\report-1.txt, name1]
Journal loaded: Journal{id=1, reportMap={name2=Report{, description='test report 2', file=c:\temp\report-2.txt}, name1=Report{, description='test report 1', file=c:\temp\report-1.txt}}}

Note

If autoApply is true, the Convert annotation may still be used to override or disable auto-apply conversion on a per-attribute basis. To disable auto conversion, we need to set @Convert#disableConversion=true.

Example Project

Dependencies and Technologies Used:

  • h2 1.4.196: H2 Database Engine.
  • hibernate-core 5.2.12.Final: The core O/RM functionality as provided by Hibernate.
  • JDK 1.8
  • Maven 3.3.9

Auto applying conversion based on type Example Select All Download
  • jpa-converter-auto-apply-example
    • src
      • main
        • java
          • com
            • logicbig
              • example
        • resources
          • META-INF

See Also