27

I run a JPA 2.0 native query like this:

Query query = em.createNativeQuery("SELECT NAME, SURNAME, AGE FROM PERSON");
List list = query.getResultList();

now list has all the rows returned by the query. I can iterate over them, but every entry is an Object[] where:

  • at index 0 I find NAME
  • at index 1 I find SURNAME
  • at index 3 I find AGE

Did anyone find a way to do something like this:

Map<String, Object> row = list.get(index);
String name = row.get("NAME");
String surname = row.get("SURNAME");
Integer age = row.get("AGE");

I would need this since the native query that I execute is a dynamic one and I don't know the order of the field in SELECT clause, so I don't know id the query will look like:

SELECT SURNAME, NAME, AGE FROM PERSON

or

SELECT AGE, NAME, SURNAME FROM PERSON

or even

SELECT AGE, SURNAME, NAME FROM PERSON
kovica
  • 2,443
  • 3
  • 21
  • 25
  • criteria query ? http://www.ibm.com/developerworks/java/library/j-typesafejpa/ – NimChimpsky Sep 29 '11 at 09:41
  • I don't think so, becase I'd still need Person.class behind. As I said the SQL qeury is dynamic and I actually don't know what it will look like. – kovica Sep 29 '11 at 10:51

3 Answers3

16

Which JPA are you using - Hibernate, EclipseLink or something else?

There is no standard way to do this in JPA but your specific implementation may allow it - for example, Eclipselink has a query result type hint.

http://dev.eclipse.org/mhonarc/lists/eclipselink-users/msg03013.html

Query query = entityManager.createNativeQuery(sql);
query.setHint(QueryHints.RESULT_TYPE, ResultType.Map);

For Hibernate, with javax.persistence.Query dbQuery:

org.hibernate.Query hibernateQuery =((org.hibernate.jpa.HibernateQuery)dbQuery)
.getHibernateQuery();
hibernateQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);
krishnakumarp
  • 8,967
  • 3
  • 49
  • 55
wrschneider
  • 17,913
  • 16
  • 96
  • 176
  • 4
    it appears hibernate does not have such a hint :( – chrismarx May 18 '15 at 17:36
  • 6
    It is working for me using native query like this : `NativeQueryImpl nativeQuery = (NativeQueryImpl) query;` `nativeQuery.setResultTransformer(AliasToEntityMapResultTransformer.INSTANCE);` `List> result = query.getResultList();` `Map row = result.get(0);` String value = (String) row.get("NAME"); – Marc Bouvier Jun 14 '17 at 09:21
  • 2
    The method setResultTransformer() is deprecated since Hibernate 5.2 – sgflt Feb 18 '20 at 07:25
6

As other already mentioned, older JPA does not support it, however I have workaround solution with Postgres 9.4 in my situation, while working with Jackson,

List<String> list = em.createNativeQuery("select cast(json_object_agg(c.config_key,c.config_value) as text) from myschema.configuration c")
                   .getResultList();

To use it in Bean layer use below method, otherwise directly return.

//handle exception here, this is just sample
Map map = new ObjectMapper().readValue(list.get(0), Map.class);

Few more json functions, https://www.postgresql.org/docs/9.4/static/functions-json.html. I am sure you can find same for other databases.

Darshan Patel
  • 2,839
  • 2
  • 25
  • 38
2

Take a look on this I got it when working on project that I could not use all JPA features so I tried the traditional jdbc method even if I would not recommend this but it's working for me.

@LocalBean
public class TCotisationEJB {

    @PersistenceContext(unitName="ClaimsProjectPU")
    private EntityManager em;

    @TransactionAttribute(TransactionAttributeType.NEVER)
    public List getCotisation(){
        Query query=em.createNativeQuery("select Annee,Mois,RetSonarwa from TCotisMIFOTRA2008 where matricule='10000493' order by Annee");
        List<Object[]> cotisation=query.getResultList();
        Object[] cotisationData;

         for(int i=0;i<cotisation.size();i++){
              cotisationData=cotisation.get(i);

             System.out.print("Annee: "+cotisationData[0]+" Mois :"+cotisationData[1]+" Amount       :"+cotisationData[2]+"\n");

     }  
     return query.getResultList();
     }    
}
Hash
  • 4,647
  • 5
  • 21
  • 39
AIMABLE
  • 885
  • 8
  • 5