08 März 2013

JPA: Using POJOs in SQL Queries Result Mapping Simplyfied

Because there is no Constructor Expression for native SQL queries in JPA I wrote a simple SqlResultMapper. The result mapper is inspired by EclipseLink and Hibernate:

  • http://onpersistence.blogspot.ch/2010/07/eclipselink-jpa-native-constructor.html
  • http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querysql.html#d0e13904
In contrast to these two vendor specific implementations my JpaSqlResultMapper works with every JPA implementation.

There are two important remarks:
  1. Constructor must have the same number of arguments as the result of the SQL query
  2. The result types must match
Your comment is highly appreciated!

public class JpaSqlResultMapper {

  public static <T> List<T> list(Query q, Class<T> clazz) 
    throws IllegalArgumentException {

    Constructor<?> ctor = 
     (Constructor<?>) clazz.getDeclaredConstructors()[0];
    List<T> result = new ArrayList<T>();

    List<Object[]> list = q.getResultList();
    for (Object obj : list) {
        if (ctor.getParameterTypes().length == 1) {
          obj = new Object[] { obj };
        }
        createAndAddBean(ctor, (Object[]) obj, result);
      }
    }
    return result;
  }

  private static <T> void createAndAddBean(
    Constructor<?> ctor, Object[] args, List<T> result) {
    try {
      T obj = (T) ctor.newInstance(args);
      result.add(obj);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }
}

1 Kommentar:

Matthias Huber hat gesagt…

Funktioniert einwandfrei. Wenn man mehrere Konstruktoren in der TO-Klasse hat, ist die Reihenfolge relevant.