Spring boot 从存储库接口检索列表到DTO列表类的最佳方法是什么

Spring boot 从存储库接口检索列表到DTO列表类的最佳方法是什么,spring-boot,spring-data-jpa,spring-data,dto,Spring Boot,Spring Data Jpa,Spring Data,Dto,在DTO包中有一个类名DailyElectric,它包含 最大值、最小值、总和、平均值(含getter和setter) public class DailyElectricity implements Serializable { private static final long serialVersionUID = 3605549122072628877L; private LocalDate date; private Long sum; private Doub

在DTO包中有一个类名DailyElectric,它包含 最大值、最小值、总和、平均值(含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);

它无法转换为dto类

问题是spring无法解决如何将查询结果转换为您期望的自定义对象DailyElectric;为了使这种映射成为可能,您需要做两件事:

  • 创建一个构造函数,以便可以创建一个新对象,并通过查询的每一行生成的值对其进行初始化:

    public DailyElectricity (Long max,Long sum,Long min,Double average){    
        this.sum=sum;
        this.average=average;
        this.min=min;
        this.max=max;   
    }
    
  • 然后在
    hourlylectricityrepository

    @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);
    
    @Query(“选择新的com.example.dailyElectrical(最大(a.generatedElectricity)、总和(a.generatedElectricity)、最小(a.generatedElectricity)、平均(a.generatedElectricity))从HourlyElectricity a where DATE a where DATE格式(读取“,%Y-%m-%d”)=日期格式(CURDATE()-1,%Y-%m-%d”)和面板id=:panelId”)
    列出getStaticsDailyElectricity(@Param(“panelId”)长panelId);
    
    • 请注意我在查询中使用的包名(com.example.dailyElectrical),并确保在测试之前使用了与项目对应的正确包名
  • 如果使用(DTO),则它们必须包含构造函数。尝试将其添加到DTO中

    但最好避免使用样板代码:

    @Value
    public class DailyElectricity {
      private LocalDate date;
      private Long sum;
      private Double average;
      private Long min;
      private Long max;
    }
    
    另一种方法是使用:

    在我看来,最好使用它们,因为它们更简单,并且有一些优点(请参阅提供的手册)

    请注意,在使用投影时,最好在查询中使用别名。它们必须与投影中对应的字段名/getter匹配,例如:

    "select max(a.generatedElectricity) as max, ..."
    
    已更新

    不幸的是,在SpringBoot2.0+中,基于类的投影无法正常工作(与SB1.5+不同,请参见may working)。在修复此错误之前,我们可以使用DTO

    更新2


    我错了-当我们在自定义查询中使用基于类的投影时,无论Spring Boot的版本如何,我们都必须使用它的构造函数

    我使用这个方法,但它在query中总是空的(“选择max(a.generatedElectricity)作为max,sum(a.generatedElectricity)作为sum,min(a.generatedElectricity)作为min,avg(a.generatedElectricity)作为小时电导率a的平均值,其中DATE_格式(读取时间,'%Y-%m-%d')=DATE_格式(CURDATE(),'%Y-%m-%d')和panel_id=:panelId”)列表获取StatisticsDailyElectricity(@Param(“panelId”)长panelId);@pedramezzati您指的方法是什么?在我的服务类列表ListDailyElectrical=HourlYelectricTyrepository.GetStatisticsDailyelectricity(panelId);@pedramezzati请检查my:as基于类的投影及其在此中的用法。@pedramezzati并尝试将别名更改为小写。
    public interface DailyElectricity {
      LocalDate getDate();
      Long getSum();
      Double getAverage();
      Long getMin();
      Long getMax();
    }
    
    "select max(a.generatedElectricity) as max, ..."