새소식

반응형
Java/Spring

[MyBatis] #{} 와 ${} 의 차이

  • -
반응형

MyBatis 를 사용할 때 데이터를 사용하는 대입과 치환 방법 2가지가 있다.

 

#{} 방법
//Model
public class VOModel {
    String name;
    ...getter, setter 생략
}

<mapper namespace="mapper">

    <select id="selectId" parameterType="VOModel">
        SELECT * FROM test_table WHERE name = #{name}
    </select>
</mapper>

위와 같이 #{name} 을 사용하게 되면 아래와 같이 치환된다. name 의 값이 abc 라고 하면 아래와 같다.

SELECT * FROM test_table WHERE name = 'abc'

#{} 으로 사용하게 되면 변수에 작은 따옴표(')가 자동으로 붙여 쿼리가 수행되기 때문에 작은따옴표를 따로

붙일 필요가 없다.

 

좀더 깊이 들어가자면 #{} 를 사용하게 되면 처음 쿼리는 아래와 같다.

<mapper namespace="mapper">
    <select id="selectId" parameterType="VOModel">
        SELECT * FROM test_table WHERE name = ?
    </select>
</mapper>

#{name} 자리에는 쿼리문을 수행하는 preparedStatement 가 생성되어 물음표(?)를 넣어 파싱하게 되고 

컴파일 후 실행할 때 값을 바인딩 하고 쿼리문이 수행된다. 이때 ? 자리에는 값을 바인딩하는데

작은 따옴표('')가 자동으로 붙어 바인딩 된다.

 

이러한 역할로 인해 SQL Injection 공격을 예방할 수 있다.

또한 PreparedStatement 객체는 SQL 쿼리문을 파싱하는 과정을 캐시에 담아놓고 사용하기 때문에

반복적인 쿼리문을 사용할 때 효율적이다.

 

 

 

${} 방법
<mapper namespace="mapper">
    <select id="selectId" parameterType="VOModel">
        SELECT * FROM test_table WHERE name = ${name}
    </select>
</mapper>

Statement 방식인 ${name} 과 같이 사용하게 되면 ${name} 자리에 값이 바인딩된 채로 쿼리문을 수행하게 된다.

그래서 매번 값이 바뀔때마다 새로운 쿼리문으로 받아들여 SQL 쿼리문을 파싱해야 하기 때문에

성능상 좋지 않다.

SELECT * FROM test_table WHERE name = abc

 

또한 작은따옴표(')를 자동으로 붙여주지 않아 SQL Injection 공격에 취약하다.

 

하지만 아에 사용 안하는건 아니다.

동적으로 테이블명이 바껴야할때 사용하기도 한다.

#{} 를 테이블명에 사용하게되면 작은따옴표(')가 자동으로 붙어 에러가 나기 때문에 ${} 대입방법을 사용한다.

 

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.