본문 바로가기
Java

[java]Mybatis에서 #{}과 ${}차이

by 개발하자구 2023. 6. 14.

 

<select id="ZcomSelectList" resultType="ZcompanyDTO" parameterType="Criteria">
     select * from zcompany where (1) ${swhere}	
     order by ${sst} ${sod}					      
</select>

<select id="ZcomSelectList" resultType="ZcompanyDTO" parameterType="Criteria">
     select * from zcompany where (1) ${swhere}	
     order by #{sst} #{sod}					      
</select>

 

#{}

- 파라미터가 String 형태로 들어와 자동적으로 '파라미터' 형태가 된다.

  ex) #{user_id}의 user_id의 값이 abc라면 쿼리문에는 user_id = 'abc'의 형태가 된다.

- 쿼리 주입을 예방할 수 있어 보안측면에서 유리하다.

 

 

 

<select id="select" resultType="String" parameterType="Map">
    SELECT
        name AS name
    FROM
        user
    WHERE
        id = #{id}
</select>

MyBatis에서 위와 같은 #{}이 사용된 쿼리문이 실행되면 아래와 같이 쿼리문에 ?가 생기며 파싱된다.

SELECT
    name AS name, email AS email
FROM
    user
WHERE
    id = ?

- 쿼리문을 작성할 때 #{}을 사용하는 경우 PreparedStatement를 생성하게 되는데 위의 ?에 파라미터가 바인딩되어 수행된다. 이렇게 파싱된 쿼리문은 재활용(캐싱)되기 때문에 효율적이다.

- 그리고 변수에 작은 따옴표(‘)가 자동으로 붙여 쿼리가 수행되기 때문에 '#{id}'와 같은 식으로 쿼리문을 작성하지 않아도 된다. 이러한 특성으로 테이블 설계가 user_1, user_2과 같이 분리되어 구성되어 있을 때, 아래와 같은 식으로는 작성할 수 없다.

 

 

 

${}

- 파라미터가 바로 출력된다.

- 해당 컬럼의 자료형에 맞추어 파라미터의 자료형이 변경된다.

- 쿼리 주입을 예방 할 수 없어 보안측면에서 불리하다. 그러므로, 사용자의 입력을 전달할 때는 사용하지 않는편이 낫다.

- 테이블이나 컬럼명을 파리미터로 전달하고 실을 때, #{}은 자동으로 붙어서 이 경우에는 사용할 수 없다.

 

- 값이 넣어진 채로 쿼리문이 수행된다. 그렇기 때문에 파라미터의 값이 바뀔 때마다 항상 쿼리문 파싱을 진행해야 한다. 즉, 성능상의 단점이 존재한다.

- 그리고 쿼리문에 #{}을 사용한 것과 다르게 작은 따옴표(‘)가 붙지 않기 때문에 아래처럼 테이블 이름이나 컬럼 이름을 동적으로 결정할 때 사용할 수 있다.

 

 

참조 : https://logical-code.tistory.com/25

 

Mybatis 에서 #{} 과 ${}의 차이

Mybatis 에서 #{} 과 ${}의 차이/* * [개정 이력] * 2017.12.01 내용 보충 */ 회사에 취직하고나서, 쿼리문을 작성하는데 이상한 점을 발견했다.바로 Mybatis 를 이용해 XML에 쿼리문을 작성하는데, 파라메터

logical-code.tistory.com

          https://mine-it-record.tistory.com/300

 

[MyBatis] Mybatis_파라미터 #{} 과 ${} 의 차이

SPRING 에서 mybatis를 사용하다 보면 mapper에서 보이는 '#' 과 '$' 특히 나는 기존에 배울때 '#'에 대해서만 배웠기 때문에 '$' 표현이 생소하기 때문에 어떤 의미인지 공부하며 기록해두고자 한다. 우

mine-it-record.tistory.com

          https://madplay.github.io/post/difference-between-dollar-sign-and-sharp-sign-in-mybatis

 

MyBatis에서 샾(#{})과 달러(${})의 차이는 무엇일까?

마이바티스(MyBatis)에서 XML 파일에 쿼리문을 작성할 때, 샾(#{}) 기호와 달러(${}) 기호의 차이점은 무엇일까?

madplay.github.io

 

 

-------------------------------------------------------------------------------------------------------------------------------

 

#{}

>mapper

SELECT * FROM mineTest 

WHERE num = #{num} AND id = #{id}

이런식으로 작성된 쿼리문은 다음과 같이 오라클로 전달되어 수행된다.

 

>oracle로 전달

SELECT * FROM mineTest 

WHERE num = ? AND id = ?

 

>실제 수행 쿼리문

SELECT * FROM mineTest mt

WHERE num = 34 AND id = 'mine'

 

 

 

 

${}

 

>mapper

SELECT * FROM mineTest 

WHERE num = ${num} AND id = ${id}

 

이런식으로 작성된 쿼리문은 다음과 같이 오라클로 전달되어 수행된다.

 

>oracle로 전달

SELECT * FROM mineTest 

WHERE num = 34 AND id = mine

 

>실제 수행 쿼리문

SELECT * FROM mineTest mt

WHERE num = 34 AND id = mine

 

 

 

 

이렇게 간단하게 둘의 실제 실행방식의 차이점을 확인해 봤는데

더 깊숙하게 들어가 보자면 

 

1. preparedStatement 와 Statement 의 차이점이라 보면된다 (쉽게 동적 과 정적의 차이)

 

2. 오라클로 전달할때 '?' 와 '값' 형태로 바인딩 된다.

 

3. preparedStatement 방식인 #{} 은 쿼리의 재사용이 가능하지만

Statement 방식인 ${} 은 재사용이 불가능하며 새로운 쿼리로 인식하기 때문에 성능상 차이가 존재한다.

 

- 성능상에 차이가 있다하지만 ${} 가 단점만 존재하는게 아니라 옵티마이저 수행 계획에 이점을 주는 경우도 존재하며 자주 바뀌지 않거나 사용자의 입력을 받는 경우 (ex 테이블 명 , 컬럼 명) 에 사용해 주면 좋다.

 

- #{} 은 사용자의 입력을 받거나 데이터가 많은 경우에 주로 사용한다.

 

(대부분 ${} 보다는 #{} 위주로 작성하는 경우가 많다.)

 

4. ${}을 사용할 경우 SQL Injection 보안 위험이 발생하는 경우가 발생한다.

 

- 위의 예시를 보여준것처럼 ${}는 #{} 과 달리 문자열에 자동으로 ' ' 쿼터를 감싸주지 않는다.