본문 바로가기
Error

[Java / Spring / JPA / QueryDsl / Error] - No constructor found for class com.namji.datacollection.dto.response.DataStatisticsResponse with parameters: [class java.lang.Long, class java.lang.String, class java.lang.Double]

by nam_ji 2024. 7. 31.

No constructor found for class cohttp://m.namji.datacollection.dto.response.DataStatisticsResponse with parameters: [class java.lang.Long, class java.lang.String, class java.lang.Double]

에러 원인

  • QueryDSL을 이용하여 통계 쿼리를 작성하고 Postman으로 API 테스트를 하면서 발생한 에러입니다.
  • 찾아보니 QueryDsl을 사용하다 보면 필요한 컬럼만 조회하거나 서브 쿼리를 이용하여 컬럼을 추가할 때 Projections.constructor에 조회결과를 리턴 받을 클래스를 지정하는데 해당 클래스의 생성자에 조회 결과의 컬럼 리턴 타입과 리턴 개수를 정확하게 해야 한다고 해서 작성된 코드를 한번 살펴봤습니다.
  • QueryDsl
    •  
    • @Override public DataStatisticsResponse getDeviceStatistics(DataStatisticsRequest request) { QDevice qDevice = QDevice.device; QData qData = QData.data; return jpaQueryFactory .select(Projections.constructor( DataStatisticsResponse.class, qDevice.deviceId.as("id"), qDevice.serialNumber, qData.dataSet.avg().as("averageData"))) .from(qDevice) .join(qData).on(qDevice.deviceId.eq(qData.device.deviceId)) .where(qDevice.serialNumber.eq(request.getSerialNumber()), qData.recordedAt.between(request.getStartDate(), request.getEndDate())) .groupBy(qDevice.deviceId, qDevice.serialNumber) .fetchOne(); }
    • 여기서 반환되는 값을 device의 id(Long 타입)와 device의 serialNumber(String 타입)와 device의 dataSet (int 타입)입니다.
  • Response
    • package com.namji.datacollection.dto.response;
      
      import lombok.AllArgsConstructor;
      import lombok.Getter;
      import lombok.NoArgsConstructor;
      
      @Getter
      @NoArgsConstructor
      @AllArgsConstructor
      public class DataStatisticsResponse {
        private Long DeviceId;
        private String serialNumber;
        private int DeviceStatistics;
      }
    • Response에도 똑같이 Long 타입과 String 타입, int 타입으로 되어 있어 뭐가 문제일까 봤더니
  • 에러 문구에서 원인을 발견할 수 있었습니다.
    에러 마지막 문구를 보면 Long, String, Double이 있어 왜일까 생각해보니 dataSet을 반환할 때 평균 값을 반환하기 때문에 Double로 받아야 한다는 것을 알 수 있었습니다.

해결 방안

  • 조회하는 컬럼과 반환 받는 타입 및 반환 개수를 확인해보면 됩니다.
  • 저와 같이 리턴 값들 중에서 연산이 된다거나 다른 작업이 있는지도 확인해야 될 거 같습니다.
  • 에러 문구에서도 힌트를 얻을 수 있으니 에러 문구도 확인해 가며 원인을 분석하면 좋을 것 같습니다.
  • package com.namji.datacollection.dto.response;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import lombok.NoArgsConstructor;
    
    @Getter
    @NoArgsConstructor
    @AllArgsConstructor
    public class DataStatisticsResponse {
      private Long DeviceId;
      private String serialNumber;
      private Double DeviceStatistics;
    }
  • 저는 Double로 수정하고 실행해보니 정상 동작하는 것을 확인할 수 있었습니다.