SQL

[SQL/Error] Object[]와 COUNT의 반환 타입

발달중인 망고 2024. 3. 26. 02:09

오늘은 읽는곳곳 프로젝트를 하며 마주쳤던 이슈를 적어보려 합니다!! (간단 주의)

 

요즘 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() 함수의 결과를 직접적으로 처리할 수 있게 해 줍니다.

짧은 글이지만 읽어주셔서 감사합니다~!😁