들어가기에 앞서..
inflearn과 유사한 강의 시스템 API를 제작하던 중 강의 저장을 테스트 하던 상황에서
MyBatis의 Data Conversion Error가 계속 나고 있는 상황이였다.
무엇인고 하니 저장은 문제없이 잘 되고 데이터도 직접 확인해보니 이상이 없는 상황에서
findById 부분 result Set에서 type이 안맞아 conversion에 실패 했다는것
처음엔 작성한 코드만 보고 잘못된 부분을 도저히 못찾겠어서 h2 version 도 바꿔보고 mybatis 버젼도 수정하는 등
별 짓을 다 해봤으나.. 결국 설정 문제는 아닌것으로 판명
Debug 시작
SELECT 문도 문제 없이 잘 돌아가는 상황
가장 하단의 에러 로그를 보아하니 For input string : "Lecture1" 에서 NumberForamtException이 발생 했다는 것이다.
process를 쭉 따라가던 와중에 pareInt exception을 발생시키는 부분 발견
NAME의 parameterType : "int" ?
String 타입의 NAME을 가져와야하는데 parameterType이 int라니? 쌩뚱맞다.
DB 테이블 Column을 NUMBER로 설정 한 줄 알고 확인했으나 VARCHAR로 정의 되어있음
그렇다면 저 parameterType이 왜 int로 설정되는지 constructor의 getParameterTypes() 부분을 살펴본다
parameterTypes를 그대로 clone 해오는 모습
constructor 내부 parameterTypes를 살펴보면
순서대로 String, int, int, String, String, String, long 인 것을 확인 할 수 있다.
왜 이렇게 들어가있는지
constructor를 생성하는 부분을 살펴보자
getDeclaredConstructors() 에서 constructors를 가져오는 것을 확인
요약하면 클래스의 모든 생성자를 반환해준다고 한다.
결과적으로 내가 작성한 생성자를 토대로 생성자에 들어가는 parameterType을 꺼내온 후 순서대로 매핑 하는 상황
😲 그렇다면?
그랬다...... select문을 생성자 파라미터 순서에 맞게 작성해야 mybatis에서 resultSet을 Setting할 때 문제 없이 변환하는 것..!
(위에서 본대로 순서대로 매핑이라서)
별생각없이 이름으로 알아서 매핑된다고 생각하고
DB에서 자동으로 증가시켜주는 Sequence ID를 사용하다보니 생성자에 명시하지 않아서 생긴 문제였다.
변경 후
테스트 코드
문제 없이 잘 테스트 되는 모습
결론
내가 사용하는 기술이 내부적으로 어떻게 동작한다는 이해가 없는 상태로 기능만 사용하다보니
이런 문제가 발생하게 되는 것은 시간 문제라는 것을 뼈저리게 느끼고 애꿎은 설정탓만 하며 문제를 빠르게 해결하지 못하는 상황이 생겼다.
현재 Spring의 내부 동작 구조를 이해하는 공부를 진행 중에 있다보니
사용하는 기술이 내부적으로 어떻게 동작하는지를 명확하게 이해하고 기술을 사용 하는 것이 무엇보다도 중요하다는 것을
직접 체감하게 되는 경험이였다.
https://github.com/f-lab-edu/infrun
GitHub - f-lab-edu/infrun: 교육 강의 플랫폼
교육 강의 플랫폼. Contribute to f-lab-edu/infrun development by creating an account on GitHub.
github.com