오늘은 읽는곳곳 프로젝트를 하며 마주쳤던 이슈를 적어보려 합니다!! (간단 주의)
요즘 TestCode와 Refatoring을 하고 있어서 프로젝트를 들여다 볼일이 많은데요. 오늘도 Swagger
로 모든 동작이 정상동작하는지 확인하다가(아직 테스트 커버리지가 높지 못해서...) 오류를 발견하게 되었습니다.
문제 상황
❗ 바로 독서장소에 걸려있는 태그 중 상위 5개만 가져오는 API
가 500 에러를 뿜으면서 죽어있는 것을 발견했습니다.
✅일단 오류 상황을 인지하기 위해서 ISSUE등록
을 해주었구요.
보기 힘든 코드 이긴 하지만.. 리펙토링 과정에 있습니다..
에러로그
✅ 다음으로는 EC2에 접근해서 에러로그를 보았는데요.
❌ Long타입을 Integer로 강제 변환하려다 생긴 오류라고 해석되네요.
2024-03-25T16:35:09.526Z ERROR 7 --- [nio-8082-exec-7] o.a.c.c.C.[.[.[/].[dispatcherServlet]
: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
[Request processing failed: java.lang.ClassCastException: class java.lang.Long cannot be
cast to class java.lang.Integer (java.lang.Long and java.lang.Integer are in module java.base
of loader 'bootstrap')] with root cause
✅ 즉, 잘못된 값을 캐스팅
하여서 일어났던 일이었습니다.
문제의 코드 부분
PinServiceImpl 일부
List<Object[]> taggeds = taggedRepository.mCountByPinId(pin.getId());
List<TagCountRespDto> tagCountRespDtos = taggeds.stream()
.map(tagged -> new TagCountRespDto(
(String) tagged[0],
(Integer) tagged[1])).toList();
TaggedRepository
//pin에 tag들에 대한 count개수 상위 5개
@Query("SELECT t.tag.content, COUNT(t) FROM Tagged t WHERE t.pin.id = :pinId GROUP BY t.tag.content ORDER BY COUNT(t) DESC LIMIT 5")
List<Object[]> mCountByPinId(@Param("pinId") Long pinId);
레파지토리 부분에서 content와 COUNT(t)를 가져오길래 String과 Interger로 받았었는데,,
COUNT는 일반적으로 Long 타입으로 반환되는 경우가 많다고 합니다.
이후 Integer -> Long
으로 바꿔주었습니다.
해결😮
안전한 캐스팅 방법!
마지막으로 안전한 캐스팅방법을 알아보며 글을 마무리하겠습니다.
COUNT()함수와 반환 타입
- COUNT() 함수는 SQL 쿼리에서 특정 조건을 만족하는 행의 수를 계산하는 데 사용됩니다.
- 대부분의 데이터베이스 시스템에서, COUNT() 함수는 Long 타입의 값을 반환합니다. 이는 대량의 데이터를 처리할 수 있는 충분한 크기여서 그렇다고 합니다~
JAVA와 JPA에서의 처리
- JPA 쿼리의 결과로 Object[] 형태로 데이터를 받아올 때, COUNT() 함수의 결과 역시 이 배열의 일부로 포함됩니다.
- 하지만, Java에서는 타입 안전성을 보장하기 위해 명시적인 타입 캐스팅이 필요합니다. COUNT()의 결과를 Integer로 처리하려 할 때
ClassCastException
이 발생할 수 있습니다. 이는 Long 타입을 Integer 타입으로직접 캐스팅할 수 없기
때문입니다.
안전한 타입 캐스팅 방법
- 방법 1: 반환된 COUNT() 값은 Number 타입으로 캐스팅한 후, intValue() 또는 longValue() 메소드를 사용하여 필요한 타입으로 변환합니다.
((Number) tagged[1]).intValue();
- 방법 2: TagCountRespDto와 같은 DTO(Data Transfer Object)를 설계할 때, 가능한 모든 숫자 타입을 수용할 수 있는 long 타입을 사용합니다. 이는 타입 변환 없이 COUNT() 함수의 결과를 직접적으로 처리할 수 있게 해 줍니다.
짧은 글이지만 읽어주셔서 감사합니다~!😁
'SQL' 카테고리의 다른 글
[SQL] 인덱스를 안탔다??! 암시적 형변환, 풀테이블 스캔 문제 (0) | 2024.08.02 |
---|---|
[SQL/Error] 필드타입 변경 : TEXT길이 연장하기 (0) | 2024.03.10 |
[SQL] WHERE, ORDER BY (1) | 2022.10.20 |
[데이터베이스] SQL 기본 탐구 , Oracle (4) | 2022.10.13 |