Lösung für JPQL-Abfragen
Dies wird für JPQL-Abfragen innerhalb der JPA-Spezifikation unterstützt .
Schritt 1 : Deklarieren Sie eine einfache Bean-Klasse
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;
}
}
Schritt 2 : Bean-Instanzen von der Repository-Methode zurückgeben
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();
}
Wichtige Notizen
- Stellen Sie sicher, dass Sie den vollständig qualifizierten Pfad zur Bean-Klasse einschließlich des Paketnamens angeben. Wenn beispielsweise die Bean-Klasse aufgerufen wird
MyBean
und sich im Paket befindet com.path.to
, lautet der vollständig qualifizierte Pfad zur Bean com.path.to.MyBean
. Einfach die Bereitstellung MyBean
nicht funktionieren (es sei denn , die Bean - Klasse im Standardpaket ist).
- Stellen Sie sicher, dass Sie den Bean-Klassenkonstruktor mit dem
new
Schlüsselwort aufrufen . SELECT new com.path.to.MyBean(...)
wird funktionieren, während SELECT com.path.to.MyBean(...)
nicht.
- Stellen Sie sicher, dass die Attribute in genau der Reihenfolge übergeben werden, die im Bean-Konstruktor erwartet wird. Der Versuch, Attribute in einer anderen Reihenfolge zu übergeben, führt zu einer Ausnahme.
- Stellen Sie sicher, dass die Abfrage eine gültige JPA-Abfrage ist, dh keine native Abfrage.
@Query("SELECT ...")
, oder @Query(value = "SELECT ...")
, oder @Query(value = "SELECT ...", nativeQuery = false)
wird funktionieren, während @Query(value = "SELECT ...", nativeQuery = true)
wird nicht funktionieren. Dies liegt daran, dass native Abfragen ohne Änderungen an den JPA-Anbieter übergeben und für das zugrunde liegende RDBMS als solches ausgeführt werden. Da new
und com.path.to.MyBean
sind keine gültigen SQL-Schlüsselwörter, löst das RDBMS dann eine Ausnahme aus.
Lösung für native Abfragen
Wie oben erwähnt, ist die new ...
Syntax ein JPA-unterstützter Mechanismus und funktioniert mit allen JPA-Anbietern. Wenn es sich bei der Abfrage selbst jedoch nicht um eine JPA-Abfrage handelt, dh um eine native Abfrage, new ...
funktioniert die Syntax nicht, da die Abfrage direkt an das zugrunde liegende RDBMS weitergeleitet wird, das das new
Schlüsselwort nicht versteht, da es nicht Teil von ist der SQL-Standard.
In solchen Situationen müssen Bean-Klassen durch Spring Data Projection- Schnittstellen ersetzt werden.
Schritt 1 : Deklarieren Sie eine Projektionsschnittstelle
package com.path.to;
public interface SurveyAnswerStatistics {
String getAnswer();
int getCnt();
}
Schritt 2 : Geben Sie die projizierten Eigenschaften aus der Abfrage zurück
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();
}
Verwenden Sie das AS
Schlüsselwort SQL , um Ergebnisfelder Projektionseigenschaften für eine eindeutige Zuordnung zuzuordnen.
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..........