logo

MyBatis를 사용하면

#{}은 ''를 포함한 매핑 ${}은 ''를 포함하지 않고 매핑이라 단순하게 알고있지만, 좀더 세심하게 살펴보자.


우선 PreparedStatement와 Stament를 공부하자.

Stament 코드는 다음과 같다.

String sqlstr = "SELECT name, memo FROM TABLE WHERE num = " + num 
Statement stmt = conn.credateStatement(); 
ResultSet rst = stmt.executeQuerey(sqlstr);

쿼리문에 파라미터를 붙여주어, SQL문을 실행한다.


NUM 값이 1이라면, 다음 SQL문이 DBMS로 전송된다.

SELECT name, memo FROM TABLE WHERE num = 1


NUM 값이 2라면, 다음 SQL문이 DBMS로 전송된다.

SELECT name, memo FROM TABLE WHERE num = 2


서도다른 두 쿼리가 DBMS로 전송되고 DBMS는 다르게 인지하기 때문에 매번 컴파일을 실행한다.

따라서 NUM값을 N개로 하여 조회하면 N번의 컴파일이 이루어질 것다.


PrparedStament는 이 점을 보안 할 수 있다.

PrparedStament의 코드는 다음과같다.

String sqlstr = "SELECT name, memo FROM TABLE WHERE num = ? " 
PreparedStatement stmt = conn.prepareStatement(sqlstr); 
pstmt.setInt(1, num);
ResultSet rst = pstmt.executeQuerey(); 
<br/>

2번라인을 보자.


2번 라인에서는 다음 SQL문을 전송하고, DBMS는 SQL문을 컴파일 한다.

SELECT name, memo FROM TABLE WHERE num = ? 


SQL문이 실행될때 전송된 NUM값이 파라미터로 전송된다.

전송된 NUM값이 ?에 바인딩되어 SQL문을 실행한다.


따라서 N개의 NUM으로 SQL문을 실행하여도, 한번의 컴파일로 해결 할 수 있다.

또한 SQL문 원본은 이미 고정되어 컴파일되어있기때문에

어떤 파라미터값이 바인딩 되어도 SQL문은 고정되며 이로 인하여 SQL Injection을 보안하는 것에 좋다.


그럼 Stament 코드를 왜쓰는가?

파라미터가 아닌, SQL문을 다이나믹하게 하는 것에 사용한다.

예를들어 다음과 같을 것이다.

String sqlstr = "SELECT name, memo FROM TABLE_" + num; 
PreparedStatement stmt = conn.prepareStatement(sqlstr); 
pstmt.setInt(1, num);
ResultSet rst = pstmt.executeQuerey(); 
<br/>

NUM값에 따라 테이블명을 변경하여 다이나믹하게 SQL문을 작성할 때 유용하다.

그러나 SQL Injection 공격에 취약하기 때문에, 개발자가 별도의 설정을 해주어야한다.


그럼 MyBatis에서 #{}, ${}의차이는?

#{}은 PreparedStament이다. #{} 구문은 ? 로 변경되어 DBMS에 SQL문이 캐싱되어진다.

추후에 바인딩되기 때문에 ?값이 달라져도 같은 컴파일이 된 내용을 재사용할 수 있다.

또한 ''가 자동으로 생성된다.


${} Statment이다. ${}구문은 ? 아닌 새로운 쿼리로 실행된다.

따라서 SQL문 자체가 변경되고 컴파일되며, SQL Injection에 취약하다.

또한 '' 가 자동으로 생성되지 않는다.



참조

http://devbox.tistory.com/entry/Comporison

https://en.wikipedia.org/wiki/Prepared_statement



CommentCount 0
이전 댓글 보기
등록
이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
TOP