PROGRAMMING LANGUAGE/JAVA

[myBatis] #와 $ 사용 시 차이점

EARTH_ROOPRETELCHAM 2020. 12. 10. 23:13
728x90
반응형

dao.xml 파일 내에 #을 쓰는 경우

SELECT TIME
FROM SUMMARY_1HOUR
WHERE 1=1
    AND TIME >= #{ queryMap.startDate }
    AND TIME < #{ queryMap.endDate }
...
  • #{ value }에는 bind된 값(value)이 들어가게 됩니다.
  • parameter가 String 형태로 들어와 자동적으로 'parameter' 형태가 됩니다.
  • 내부적으로는, preparedStatement 객체에서 #{ value }에 들어갈 파라미터 값을 set 하여 사용됩니다.
  • 즉, DB에서 변수를 bind하여 #{ value } 값이 달라져도 동일한 쿼리로 인식하게 됩니다(쿼리의 컴파일된 내용 재사용 가능).
  • 쿼리 주입을 예방할 수 있어 보안 측면에서 유리합니다.

위 예시의 경우 아래와 같이 수행됩니다.

#####################################
# queryMap.startDate = '2020-12-09' #
# queryMap.endDate = '2020-12-10'   #
#####################################

# DB로 넘어간 쿼리
SELECT TIME
FROM SUMMARY_1HOUR
WHERE 1=1
    AND TIME >= ?
    AND TIME < ?
...

# 실제 수행 쿼리
SELECT TIME
FROM SUMMARY_1HOUR
WHERE 1=1
    AND TIME >= '2020-12-09'
    AND TIME < '2020-12-10'
...

 

dao.xml 파일 내에 $를 쓰는 경우

SELECT TIME
FROM SUMMARY_P${ queryMap.table }
WHERE 1=1
    TIME >= #{ queryMap.startDate }
    TIME < #{ queryMap.endDate }
...
  • #{ value }와 달리 쿼리에 넣어진 parameter 값이 그대로 출력됩니다.
  • 주입된 위치의 자료형에 맞추어 parameter의 자료형이 변경됩니다.
  • 따라서, 쿼리 주입을 예방할 수 없어 보안 측면에서 불리합니다(사용자 입력 전달 시 사용하지 않아야 함).
  • table이나 column 명을 parameter로 전달하고자 할 때 사용합니다(#{ value }의 경우, 자동으로 ''가 붙어 이 경우 사용 불가).
  • #과 달리 값이 주입된 쿼리 자체로 수행이 됩니다(즉 ?가 없이 값이 넣어진 상태로 컴파일).

위 예시의 경우 아래와 같이 수행됩니다.

#####################################
# queryMap.table = '20201209'       #
# queryMap.startDate = '2020-12-09' #
# queryMap.endDate = '2020-12-10'   #
#####################################

#DB로 넘어간 쿼리
SELECT TIME
FROM SUMMARY_P20201209
WHERE 1=1
    TIME >= ?
    TIME < ?
...

#실제 수행 쿼리
SELECT TIME
FROM SUMMARY_P20201209
WHERE 1=1
    TIME >= '2020-12-09'
    TIME < '2020-12-10'
....

 

#과 $의 차이

#을 사용하게 되면,  DB에서 변수에 값(예: queryMap.startDate, queryMap.endDate)을 넣지 않은 ? 상태로 컴파일 되므로, 값이 변경되어도 동일한 쿼리로 인식하게 됩니다.

반면, $를 사용하면 값(예: queryMap.table)이 변경된 경우 다른 쿼리로 인식하여 새로 파싱하는 등의 작업으로 속도가 저하될 수 있습니다.

728x90
반응형