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로 수정하고 실행해보니 정상 동작하는 것을 확인할 수 있었습니다.