JPQL 查询解决方案
JPA 规范中的 JPQL 查询支持此功能。
步骤 1:声明一个简单的 Bean 类
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;
}
}
步骤 2:从存储库方法返回 Bean 实例
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();
}
重要提示
- 确保提供 Bean 类的完全限定路径,包括包名称。例如,如果调用了 Bean 类并且它位于包中,则 Bean 的完全限定路径将为 。简单地提供将不起作用(除非bean类在默认包中)。
MyBean
com.path.to
com.path.to.MyBean
MyBean
- 确保使用关键字调用 Bean 类构造函数。 将工作,而不会。
new
SELECT new com.path.to.MyBean(...)
SELECT com.path.to.MyBean(...)
- 确保以与 Bean 构造函数中预期完全相同的顺序传递属性。尝试以不同的顺序传递属性将导致异常。
- 确保查询是有效的 JPA 查询,即它不是本机查询。,或 ,或 将起作用,而将不起作用。这是因为本机查询无需修改即可传递到 JPA 提供程序,并且是针对底层 RDBMS 执行的。由于 和 不是有效的 SQL 关键字,因此 RDBMS 会引发异常。
@Query("SELECT ...")
@Query(value = "SELECT ...")
@Query(value = "SELECT ...", nativeQuery = false)
@Query(value = "SELECT ...", nativeQuery = true)
new
com.path.to.MyBean
本机查询解决方案
如上所述,语法是 JPA 支持的机制,适用于所有 JPA 提供程序。但是,如果查询本身不是 JPA 查询,也就是说,它是本机查询,则语法将不起作用,因为查询直接传递到底层 RDBMS,而底层 RDBMS 不理解关键字,因为它不是 SQL 标准的一部分。new ...
new ...
new
在这种情况下,需要用Spring数据投影接口替换Bean类。
步骤 1:声明投影接口
package com.path.to;
public interface SurveyAnswerStatistics {
String getAnswer();
int getCnt();
}
步骤 2:从查询中返回投影属性
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();
}
使用 SQL 关键字将结果字段映射到投影属性,以实现明确的映射。AS