업무를 보던 중, 호기심 천국을 자극하는 쿼리가 생겨 기록으로 남겨두게 되었다.
MyBatis를 사용하여, 서버에서 DB로 쿼리를 넘겨줄 때 문제가 발생하였다.
이전까지 자료형을 String으로 넘겨주었으나, DB NUMBER 타입에 맞추어 자료형을 double로 전환함에 따라 코드를 수정할 필요가 생겼다.
변수의 null 값을 체크할 때, Var1 자료형이 String이었을 때는 다음과 같이 체크하였다.
<if test = "Var1 == null or Var1 == ''">
문제는, Var1을 String -> double로 변환함에 따라 해당 쿼리가 의도하지 않게 작동하는 걸 발견했다.
Var1 = 0.0 을 입력하는 경우, 다음 구문이 TRUE로 반환되었다.
<if test = "Var1 == ''">
물론, 숫자를 입력하는 경우 Var1 == null 여부만 체크하면 되지만, 해당 부분이 왜 True인지 궁금해졌다.
문제의 답을 찾기 위해, MyBatis 공식 문서를 찾아보게 되었고 MyBatis는 기본적으로 OGNL 표현식을 사용하기 때문에, OGNL 표현식 공식 문서까지 찾아보았다.
Here we describe how OGNL interprets objects as various types. See below for how OGNL coerces objects to booleans, numbers, integers, and collections.
이 부분에 대한 답은, MyBatis에 있었다. MyBatis의 typeHandler를 살펴보면, primitive type으로 인자를 넘겨주더라도 전부 객체로 처리해준다. 내가 double로 인자를 넘겨주었지만 DOUBLE로 인자를 넘겨준다.
1) Var1 = double 0.0 인 경우
<if test = "Var1 == ''"> 1. Single quotation </if>
<if test = 'Var1 == ""'> 2. Dobule quotaion </if>
<if test = "Var1 == '0'"> 3. 0 with Single quotation </if>
<if test = 'Var1 == "0"'> 4. 0 with Dobule quotaion </if>
<if test = "Var1 == 0"> 5. int 0 </if>
결과는 다음과 같다
1. Single quotation
2. Dobule quotaion
4. 0 with Dobule quotaion
5. int 0
보는 바와 같이, 3번만 유일하게 False다. 그 이유는 다음과 같다.
싱글쿼테이션('')의 경우, 먼저 문자가 한 글자인지, 두 글자 이상인지를 체크한다.
만약, 문자가 두 글자 이상이라면, 내부적으로 typeHandler에 따라 double 형태로 변환되어 값 비교가 일어난다.
반면, 문자가 한 글자라면 해당 값을 아스키코드 값으로 인식한 후 아스키코드 0에 해당하는 십진수 값 48로 인식한다.
이를 확인하기 위해 다음과 같은 쿼리를 작성했다.
2) Var1 = double 48.0 인 경우 (아스키코드 0에 해당하는 십진수 48을 입력)
<if test = "Var1 == ''"> 1. Single quotation </if>
<if test = 'Var1 == ""'> 2. Dobule quotaion </if>
<if test = "Var1 == '0'"> 3. 0 with Single quotation </if>
<if test = 'Var1 == "0"'> 4. 0 with Dobule quotaion </if>
<if test = "Var1 == 0"> 5. int 0 </if>
결과는 다음과 같다
3. 0 with Single quotation