Solusi untuk kueri JPQL
Ini didukung untuk kueri JPQL dalam spesifikasi JPA .
Langkah 1 : Deklarasikan kelas kacang sederhana
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;
}
}
Langkah 2 : Kembalikan instance kacang dari metode repositori
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();
}
Catatan penting
- Pastikan untuk memberikan jalur yang sepenuhnya memenuhi syarat ke kelas kacang, termasuk nama paket. Misalnya, jika kelas kacang dipanggil
MyBean
dan berada dalam paket com.path.to
, jalur yang sepenuhnya memenuhi syarat ke kacang akan menjadi com.path.to.MyBean
. Hanya menyediakan MyBean
tidak akan berhasil (kecuali kelas kacang ada dalam paket default).
- Pastikan untuk memanggil konstruktor kelas kacang menggunakan
new
kata kunci. SELECT new com.path.to.MyBean(...)
akan bekerja, sedangkan SELECT com.path.to.MyBean(...)
tidak.
- Pastikan untuk meneruskan atribut dengan urutan yang persis sama seperti yang diharapkan dalam pembuat kacang. Mencoba meneruskan atribut dalam urutan yang berbeda akan menyebabkan pengecualian.
- Pastikan kueri tersebut adalah kueri JPA yang valid, yang bukan kueri asli.
@Query("SELECT ...")
, atau @Query(value = "SELECT ...")
, atau @Query(value = "SELECT ...", nativeQuery = false)
akan berhasil, sedangkan @Query(value = "SELECT ...", nativeQuery = true)
tidak akan berhasil. Ini karena kueri native diteruskan tanpa modifikasi ke penyedia JPA, dan dijalankan terhadap RDBMS yang mendasarinya. Karena new
dan com.path.to.MyBean
bukan kata kunci SQL yang valid, RDBMS kemudian melontarkan pengecualian.
Solusi untuk kueri asli
Seperti disebutkan di atas, new ...
sintaksis adalah mekanisme yang didukung JPA dan berfungsi dengan semua penyedia JPA. Namun, jika kueri itu sendiri bukan kueri JPA, yaitu kueri asli, new ...
sintaksis tidak akan berfungsi karena kueri diteruskan langsung ke RDBMS yang mendasari, yang tidak memahami new
kata kunci karena bukan bagian dari standar SQL.
Dalam situasi seperti ini, kelas kacang perlu diganti dengan antarmuka Proyeksi Data Musim Semi .
Langkah 1 : Deklarasikan antarmuka proyeksi
package com.path.to;
public interface SurveyAnswerStatistics {
String getAnswer();
int getCnt();
}
Langkah 2 : Kembalikan properti yang diproyeksikan dari kueri
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();
}
Gunakan AS
kata kunci SQL untuk memetakan kolom hasil ke properti proyeksi untuk pemetaan yang tidak ambigu.
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..........