with query nativas namednativequery getresultlist createnativequery create consultas java hibernate jpa

java - nativas - JPA Query.getResultList(): se utiliza de forma genérica



query native java (5)

Estoy creando una consulta compleja con varias tablas y necesito enumerar el resultado. Por lo general, estoy usando EntityManager y EntityManager el resultado a la representación de JPA:

UserEntity user = em.find(UserEntity.class, "5");

Luego puedo acceder a todos los valores como lo define la clase UserEntity del usuario. Pero, ¿cómo puedo acceder a los valores de campo devueltos desde una consulta nativa de tablas múltiples? Lo que obtengo es una lista de objetos. Eso está bien hasta ahora, pero ¿qué es "ese" Objeto? ¿Formación? ¿Mapa? ¿Colección? ...

//simpleExample Query query = em.createNativeQuery("SELECT u.name,s.something FROM user u, someTable s WHERE s.user_id = u.id"); List list = query.getResultList(); //do sth. with the list, for example access "something" for every result row.

Supongo que la respuesta es bastante simple, pero la mayoría de los ejemplos muestran el uso cuando se lanza directamente a una clase de destino.

PD: En el ejemplo podría usar los mapeos de clase, por supuesto. Pero en mi caso, someTable no están gestionadas por JPA y, por lo tanto, no tengo la entidad ni tengo una representación de clase, y como me estoy uniendo como 20 tablas, no quiero crear todas las Clases solo para acceder a los valores.


Aquí está la muestra de lo que funcionó para mí. Creo que el método put es necesario en la clase de entidad para asignar las columnas de SQL a los atributos de clase de Java.

//simpleExample Query query = em.createNativeQuery( "SELECT u.name,s.something FROM user u, someTable s WHERE s.user_id = u.id", NameSomething.class); List list = (List<NameSomething.class>) query.getResultList();

Clase de entidad

@Entity public class NameSomething { @Id private String name; private String something; // getters/setters /** * Generic put method to map JPA native Query to this object. * * @param column * @param value */ public void put(Object column, Object value) { if (((String) column).equals("name")) { setName(String) value); } else if (((String) column).equals("something")) { setSomething((String) value); } } }


Desde JPA 2.0 se puede usar un TypedQuery :

TypedQuery<SimpleEntity> q = em.createQuery("select t from SimpleEntity t", SimpleEntity.class); List<SimpleEntity> listOfSimpleEntities = q.getResultList(); for (SimpleEntity entity : listOfSimpleEntities) { // do something useful with entity; }


La consulta anterior devuelve la lista de Objetos []. Por lo tanto, si desea obtener u.name y algo de la lista, debe iterar y convertir esos valores para las clases correspondientes.


La regla general es la siguiente:

  • Si select contiene una expresión única y es una entidad, el resultado es esa entidad
  • Si select contiene una sola expresión y es una primitiva, el resultado es que primitiva
  • Si select contiene múltiples expresiones, el resultado es Object[] contiene las primitivas / entidades correspondientes

Entonces, en su list casos hay una List<Object[]> .


Si necesita una forma más conveniente de acceder a los resultados, es posible transformar el resultado de una consulta de SQL arbitrariamente compleja en una clase de Java con una molestia mínima:

Query query = em.createNativeQuery("select 42 as age, ''Bob'' as name from dual", MyTest.class); MyTest myTest = (MyTest) query.getResultList().get(0); assertEquals("Bob", myTest.name);

La clase debe ser declarada como @Entity, lo que significa que debe asegurarse de que tenga un @Id único.

@Entity class MyTest { @Id String name; int age; }