<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 보안 위험이 발생하는 경우가 발생한다.
- 위의 예시를 보여준것처럼 ${}는 #{} 과 달리 문자열에 자동으로 ' ' 쿼터를 감싸주지 않는다.
'Java' 카테고리의 다른 글
[java]공지사항 고정시키기 (0) | 2023.06.15 |
---|---|
[java]서버, jsp, servlet 버전 확인하는 방법 (0) | 2023.04.18 |
[java] 초기 환경설정 오류 잡기 (jdk-20) (0) | 2023.04.13 |
[java]Eclipse console창 한글깨짐 해결방법 (0) | 2023.04.07 |