🔥 포스팅 계기
자바, Mybatis 환경에서 if test 구문을 사용할 때 자주 보이는 오류를 해결해 보자
📍 java.lang.NumberFormatException: For input string: "N"
👉🏻 Mybatis에서 if문을 사용 시 "문자를 숫자로 인식했을 경우 발생"하는 오류
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.NumberFormatException: For input string: "N"
### Cause: java.lang.NumberFormatException: For input string: "N"
📍 String으로 보낸 파라미터를 왜 숫자형으로 인식할까?
👉🏻 if test 구문 때문에 오류가 났다면 아래 쿼리에서 문제가 되는 부분은 <if test="gender != 'N'"> 일 텐데
보다시피 숫자로 들어갈 여지 없는 String 형이다 (실제 VO에도 String으로 생성)
<select id="selectPuppyListCount" parameterType="com.test.vo.TestVO" resultType="java.lang.Integer">
SELECT
COUNT(*)
FROM PUPPY
WHERE AGE = #{age}
<if test="gender != 'N'">
AND GENDER != 'N'
</if>
</select>
📍 원인 1) String 값에 null이 오는 경우
👉🏻 String 파라미터 값에 null이 들어온다면 해당 오류 발생 가능성이 있으므로 null 체크가 필수적
👉🏻 혹은 파라미터를 넘길 때 default 값을 넣어 null이 되지 않게 하는 방법도 존재함
<select id="selectPuppyListCount" parameterType="com.test.vo.TestVO" resultType="java.lang.Integer">
SELECT
COUNT(*)
FROM PUPPY
WHERE AGE = #{age}
<if test="gender != null and gender != 'N'">
AND GENDER != 'N'
</if>
</select>
하지만 위 방법으로 오류를 해결할 수 없었다.
애초에 파라미터가 null로 들어온 것도 아니었으니 위 null 체크는 그냥 기본 베이스 정도로 생각해야 함
📍 원인 2) 싱글쿼테이션(')과 더블쿼테이션(") 위치
👉🏻 다시 한번 내 쿼리를 보면 싱글쿼테이션(')이 파라미터를 감싸고, if test문은 더블쿼테이션(")이 감싸고 있음
👉🏻 바로 이 부분이 문제가 되는데 싱글쿼테이션 때문에 'N'을 Char 형, 즉 Number Format으로 인식하는 것
<select id="selectPuppyListCount" parameterType="com.test.vo.TestVO" resultType="java.lang.Integer">
SELECT
COUNT(*)
FROM PUPPY
WHERE AGE = #{age}
<if test="gender != null and gender != 'N'">
AND GENDER != 'N'
</if>
</select>
📍 해결 1) 싱글쿼테이션(')과 더블쿼테이션(") 위치 변경
👉🏻 가장 간단한 방법으로 파라미터를 감싸는 쿼테이션을 더블쿼테이션, if test문을 감싸는 쿼테이션을 싱글쿼테이션으로 쓰면 됨
<select id="selectPuppyListCount" parameterType="com.test.vo.TestVO" resultType="java.lang.Integer">
SELECT
COUNT(*)
FROM PUPPY
WHERE AGE = #{age}
<if test='gender != null and gender != "N"'>
AND GENDER != 'N'
</if>
</select>
📍 해결 2) "N".equlas()의 사용
👉🏻문자열 비교 방법인 equlas()를 쓰는 것도 방법이 될 수 있음
<select id="selectPuppyListCount" parameterType="com.test.vo.TestVO" resultType="java.lang.Integer">
SELECT
COUNT(*)
FROM PUPPY
WHERE AGE = #{age}
<if test="gender != null and 'N'.equals(gender)">
AND GENDER != 'N'
</if>
</select>
📍 해결 3) "N".toString()의 사용
👉🏻 또 다른 문자열 비교 방법인 toString()도 가능함
<select id="selectPuppyListCount" parameterType="com.test.vo.TestVO" resultType="java.lang.Integer">
SELECT
COUNT(*)
FROM PUPPY
WHERE AGE = #{age}
<if test="gender != null and gender == 'N'.toString()">
AND GENDER != 'N'
</if>
</select>