Rozwiązanie dla zapytań JPQL
Jest to obsługiwane w przypadku zapytań JPQL w ramach specyfikacji JPA .
Krok 1 : Zadeklaruj prostą klasę fasoli
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;
}
}
Krok 2 : Zwróć instancje bean z metody repozytorium
public interface SurveyRepository extends CrudRepository<Survey, Long> {
@Query("SELECT " +
" new com.path.to.SurveyAnswerStatistics(v.answer, COUNT(v)) " +
"FROM " +
" Survey v " +
"GROUP BY " +
" v.answer")
List<SurveyAnswerStatistics> findSurveyCount();
}
Ważne notatki
- Upewnij się, że podano w pełni kwalifikowaną ścieżkę do klasy bean, w tym nazwę pakietu. Na przykład, jeśli wywoływana jest klasa bean
MyBean
i znajduje się ona w pakiecie com.path.to
, w pełni kwalifikowana ścieżka do komponentu bean będzie com.path.to.MyBean
. Samo podanie MyBean
nie zadziała (chyba że klasa bean znajduje się w domyślnym pakiecie).
- Pamiętaj, aby wywołać konstruktor klasy bean przy użyciu
new
słowa kluczowego. SELECT new com.path.to.MyBean(...)
zadziała, ale SELECT com.path.to.MyBean(...)
nie zadziała.
- Upewnij się, że atrybuty są przekazywane dokładnie w takiej samej kolejności, jak oczekiwano w konstruktorze bean. Próba przekazania atrybutów w innej kolejności doprowadzi do wyjątku.
- Upewnij się, że zapytanie jest prawidłowym zapytaniem JPA, czyli nie jest zapytaniem natywnym.
@Query("SELECT ...")
, lub @Query(value = "SELECT ...")
, lub @Query(value = "SELECT ...", nativeQuery = false)
będzie działać, ale @Query(value = "SELECT ...", nativeQuery = true)
nie będzie działać. Dzieje się tak, ponieważ natywne zapytania są przekazywane bez modyfikacji do dostawcy JPA i są wykonywane względem bazowego RDBMS jako takiego. Ponieważ new
i com.path.to.MyBean
nie są poprawnymi słowami kluczowymi SQL, RDBMS zgłasza wyjątek.
Rozwiązanie dla zapytań natywnych
Jak wspomniano powyżej, new ...
składnia jest mechanizmem obsługiwanym przez JPA i działa ze wszystkimi dostawcami JPA. Jeśli jednak samo zapytanie nie jest zapytaniem JPA, to znaczy jest zapytaniem natywnym, new ...
składnia nie będzie działać, ponieważ zapytanie jest przekazywane bezpośrednio do bazowego systemu RDBMS, który nie rozumie new
słowa kluczowego, ponieważ nie jest częścią standard SQL.
W takich sytuacjach klasy bean należy zastąpić interfejsami Spring Data Projection .
Krok 1 : Zadeklaruj interfejs projekcji
package com.path.to;
public interface SurveyAnswerStatistics {
String getAnswer();
int getCnt();
}
Krok 2 : Zwróć przewidywane właściwości z zapytania
public interface SurveyRepository extends CrudRepository<Survey, Long> {
@Query(nativeQuery = true, value =
"SELECT " +
" v.answer AS answer, COUNT(v) AS cnt " +
"FROM " +
" Survey v " +
"GROUP BY " +
" v.answer")
List<SurveyAnswerStatistics> findSurveyCount();
}
Użyj AS
słowa kluczowego SQL, aby odwzorować pola wynikowe na właściwości rzutowania w celu jednoznacznego odwzorowania.
Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Unable to locate class [SurveyAnswerReport] [select new SurveyAnswerReport(v.answer,count(v.id)) from com.furniturepool.domain.Survey v group by v.answer] at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1750) at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677) at org.hibernate.jpa.spi.AbstractEnti..........