Spring Data JPA自定义JPQL查询返回类型错误,咨询正确返回类型
自定义JPQL查询的返回类型方案
你的查询仅返回了ClusterEntity的ID和计算得到的summedFrequency两个字段,并非完整的实体对象,因此无法直接使用List<ClusterEntity>作为返回类型。以下是几种可行的返回类型方案:
1. 使用Object数组
这是最直接的临时解决方案,返回List<Object[]>,数组中按查询字段顺序存储结果:
@Query("select clusters.id, " + "sum(greatest(frequencies.january, " + "frequencies.february, " + "frequencies.march, " + "frequencies.april, " + "frequencies.may, " + "frequencies.june, " + "frequencies.july, " + "frequencies.august, " + "frequencies.september, " + "frequencies.october, " + "frequencies.november, " + "frequencies.december)) summedFrequency " + "from ClusterEntity clusters " + "left join PhraseEntity phrases on phrases.cluster.id=clusters.id " + "left join FrequencyEntity frequencies on frequencies.phrase.id=phrases.id " + "where clusters.page.id = :page_id " + "group by clusters.id " ) List<Object[]> findAllClustersByPage(@Param("page_id") Integer pageId);
使用时直接强转数组元素:
for (Object[] result : results) { Integer clusterId = (Integer) result[0]; Long summedFreq = (Long) result[1]; // 业务逻辑处理 }
2. 自定义DTO(数据传输对象)
定义专门的类封装查询结果,代码可读性和维护性更好:
首先创建DTO类(注意必须提供与查询字段顺序匹配的构造方法):
public class ClusterFrequencyDTO { private Integer clusterId; private Long summedFrequency; public ClusterFrequencyDTO(Integer clusterId, Long summedFrequency) { this.clusterId = clusterId; this.summedFrequency = summedFrequency; } // 按需添加getter/setter public Integer getClusterId() { return clusterId; } public Long getSummedFrequency() { return summedFrequency; } }
修改查询语句,使用构造函数表达式返回DTO:
@Query("select new com.yourpackage.ClusterFrequencyDTO(clusters.id, " + "sum(greatest(frequencies.january, " + "frequencies.february, " + "frequencies.march, " + "frequencies.april, " + "frequencies.may, " + "frequencies.june, " + "frequencies.july, " + "frequencies.august, " + "frequencies.september, " + "frequencies.october, " + "frequencies.november, " + "frequencies.december)) summedFrequency) " + "from ClusterEntity clusters " + "left join PhraseEntity phrases on phrases.cluster.id=clusters.id " + "left join FrequencyEntity frequencies on frequencies.phrase.id=phrases.id " + "where clusters.page.id = :page_id " + "group by clusters.id " ) List<ClusterFrequencyDTO> findAllClustersByPage(@Param("page_id") Integer pageId);
注意:new关键字后必须写DTO的完整包路径。
3. 使用Spring Data投影
通过接口定义投影,无需创建实体类,适合快速场景:
首先定义投影接口:
public interface ClusterFrequencyProjection { // 别名需与查询字段的别名对应 Integer getClusterId(); Long getSummedFrequency(); }
修改查询语句,给字段添加别名:
@Query("select clusters.id as clusterId, " + "sum(greatest(frequencies.january, " + "frequencies.february, " + "frequencies.march, " + "frequencies.april, " + "frequencies.may, " + "frequencies.june, " + "frequencies.july, " + "frequencies.august, " + "frequencies.september, " + "frequencies.october, " + "frequencies.november, " + "frequencies.december)) as summedFrequency " + "from ClusterEntity clusters " + "left join PhraseEntity phrases on phrases.cluster.id=clusters.id " + "left join FrequencyEntity frequencies on frequencies.phrase.id=phrases.id " + "where clusters.page.id = :page_id " + "group by clusters.id " ) List<ClusterFrequencyProjection> findAllClustersByPage(@Param("page_id") Integer pageId);
接口的getter方法名需与查询字段的别名匹配(比如getClusterId()对应clusterId别名)。
内容的提问来源于stack exchange,提问作者Kifsif
相关产品推荐
相关产品推荐

