Nuestros investigadores estrellas agotaron sus provisiones de café, en su búsqueda día y noche por la respuesta, hasta que Liliana encontró la contestación en Bitbucket y hoy la comparte aquí.
Solución:
Solución para consultas JPQL
Esto es compatible con consultas JPQL dentro de la especificación JPA.
Paso 1: Declarar una clase de frijol simple
package com.path.to;
public class SurveyAnswerStatistics
private String answer;
private Long cnt;
public SurveyAnswerStatistics(String answer, Long cnt)
this.answer = answer;
this.count = cnt;
Paso 2: Devolver instancias de bean desde el método de repositorio
public interface SurveyRepository extends CrudRepository
@Query("SELECT " +
" new com.path.to.SurveyAnswerStatistics(v.answer, COUNT(v)) " +
"FROM " +
" Survey v " +
"GROUP BY " +
" v.answer")
List findSurveyCount();
Notas importantes
- Asegúrese de proporcionar la ruta completa a la clase de bean, incluido el nombre del paquete. Por ejemplo, si la clase de bean se llama
MyBean
y esta en paquetecom.path.to
la ruta completamente calificada al bean serácom.path.to.MyBean
. Simplemente proporcionandoMyBean
no funcionará (a menos que la clase de bean esté en el paquete predeterminado). - Asegúrese de llamar al constructor de clases de bean usando el
new
palabra clave.SELECT new com.path.to.MyBean(...)
funcionará, mientras queSELECT com.path.to.MyBean(...)
no. - Asegúrate de pasar attributes exactamente en el mismo orden que el esperado en el constructor del bean. intentando pasar attributes en un orden diferente dará lugar a una excepción.
- Asegúrese de que la consulta sea una consulta JPA válida, es decir, no sea una consulta nativa.
@Query("SELECT ...")
o@Query(value = "SELECT ...")
o@Query(value = "SELECT ...", nativeQuery = false)
funcionará, mientras que@Query(value = "SELECT ...", nativeQuery = true)
no trabajará. Esto se debe a que las consultas nativas se pasan sin modificaciones al proveedor de JPA y se ejecutan en el RDBMS subyacente como tal. Ya quenew
ycom.path.to.MyBean
no son palabras clave de SQL válidas, el RDBMS genera una excepción.
Solución para consultas nativas
Como se señaló anteriormente, el new ...
La sintaxis es un mecanismo compatible con JPA y funciona con todos los proveedores de JPA. Sin embargo, si la consulta en sí no es una consulta JPA, es decir, es una consulta nativa, el new ...
la sintaxis no funcionará ya que la consulta se pasa directamente al RDBMS subyacente, que no comprende el new
palabra clave ya que no es parte del estándar SQL.
En situaciones como estas, las clases de beans deben reemplazarse con interfaces Spring Data Projection.
Paso 1: Declarar una interfaz de proyección
package com.path.to;
public interface SurveyAnswerStatistics
String getAnswer();
int getCnt();
Paso 2: Devuelve las propiedades proyectadas de la consulta
public interface SurveyRepository extends CrudRepository
@Query(nativeQuery = true, value =
"SELECT " +
" v.answer AS answer, COUNT(v) AS cnt " +
"FROM " +
" Survey v " +
"GROUP BY " +
" v.answer")
List findSurveyCount();
Usa el Sql AS
palabra clave para asignar campos de resultados a propiedades de proyección para un mapeo inequívoco.
Esta lista de retorno de consulta SQL< Object[] > haría.
Puedes hacerlo de esta manera:
@RestController
@RequestMapping("/survey")
public class SurveyController
@Autowired
private SurveyRepository surveyRepository;
@RequestMapping(value = "/find", method = RequestMethod.GET)
public Map findSurvey()
List
Sé que esta es una pregunta antigua y ya ha sido respondida, pero aquí hay otro enfoque:
@Query("select new map(count(v) as cnt, v.answer) from Survey v group by v.answer")
public List> findSurveyCount();