在DTO包中有类名DailyElectricity,它包含max,min,sum,getter和setter的平均值
public class DailyElectricity implements Serializable {
private static final long serialVersionUID = 3605549122072628877L;
private LocalDate date;
private Long sum;
private Double average;
private Long min;
private Long max;
}
有一个接口,它的工作是从数据库中获取数据
@RestResource(exported = false)
public interface HourlyElectricityRepository
extends PagingAndSortingRepository<HourlyElectricity,Long> {
Page<HourlyElectricity> findAllByPanelIdOrderByReadingAtDesc(Long panelId,Pageable pageable);
@Query("SELECT max(a.generatedElectricity), sum(a.generatedElectricity),min(a.generatedElectricity),max(a.generatedElectricity) from HourlyElectricity a where DATE_FORMAT(reading_at,'%Y-%m-%d')=DATE_FORMAT(CURDATE()-1,'%Y-%m-%d') and panel_id=:panelId")
List<DailyElectricity> getStaticsDailyElectricity(@Param("panelId")Long panelId);
}
它编译没有任何异常,但当我调用它给它时
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [com.techtrial.dto.DailyElectricity]
它无法转换为dto类
问题是,spring无法弄清楚如何将查询结果转换为您期望的自定义对象DailyElectricity;为了使这种映射成为可能,您需要做两件事:
public DailyElectricity (Long max,Long sum,Long min,Double average){
this.sum=sum;
this.average=average;
this.min=min;
this.max=max;
}
HourlyElectricityRepository
中使用以下结构进行查询
@Query("SELECT new com.example.DailyElectricity( max(a.generatedElectricity), sum(a.generatedElectricity),min(a.generatedElectricity),avg(a.generatedElectricity)) from HourlyElectricity a where DATE_FORMAT(reading_at,'%Y-%m-%d')=DATE_FORMAT(CURDATE()-1,'%Y-%m-%d') and panel_id=:panelId")
List<DailyElectricity> getStaticsDailyElectricity(@Param("panelId")Long panelId);
请注意我在查询中使用的包名(com.example.DailyElectricity),并确保在测试之前使用与您项目对应的正确包名。如果您使用的是class-based projections(DTO),则必须包含构造函数。尝试将其添加到您的DTO。
但最好使用Lombok来避免样板代码:
@Value
public class DailyElectricity {
private LocalDate date;
private Long sum;
private Double average;
private Long min;
private Long max;
}
另一种方法是使用interface-based projections:
public interface DailyElectricity {
LocalDate getDate();
Long getSum();
Double getAverage();
Long getMin();
Long getMax();
}
IMO最好使用它们因为它们更简单并且它们具有一些优点(参见提供的手册)。
请注意,一种好的做法是在使用投影时在查询中使用别名。它们必须与投影中的对应字段名称/ getter匹配,例如:
"select max(a.generatedElectricity) as max, ..."
更新
不幸的是,在Spring Boot 2.0+中,基于类的投影不能像expected那样工作(与SB 1.5+不同 - 请参阅demo工作)。 在修复此错误之前,我们可以使用DTO constructor in the query。
更新2
我错了 - 当我们使用基于类的投影和自定义查询时,无论Spring Boot的版本如何,我们都必须使用它的构造函数。