기본 콘텐츠로 건너뛰기

181115 Mybatis: #, $

Mybatis: #, $


0. #, $ 비교

SELECT *
FROM TEMP
WHERE 1=1
  AND TEMP_ID = #{tempId}
cs
위와 같은 쿼리를 실행

1) DB에서는

SELECT *
FROM TEMP
WHERE 1=1
  AND TEMP_ID = ?
cs
    이렇게 쿼리문에 대한 의미 파악 시작
2) 구문 분석 및 파싱 진행 = PreparedStatement
 - 예를 들어, tempId에 1이라는 값이 들어가면 위의 파싱된 구문을 재활용
 - 단, DB 옵티마이저의 수행계획은 동일
 - 인덱스 스캔으로 인한 성능 저하 가능성 존재

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

SELECT *
FROM TEMP
WHERE 1=1
  AND TEMP_ID = ${tempId}
cs
위 쿼리의 경우,


SELECT *
FROM TEMP
WHERE 1=1
  AND TEMP_ID = 1
cs

1) ${tempId}가 1인 경우 위 쿼리로 실행
 - DB에서는 의미 파악, 파싱 시작= Statement
 - 상수로 치환하여 수행 = 값이 변경될 때마다 파싱 진행
2) SQL injection에 취약



※ PreparedStatement, Statement
 - 두 인터페이스의 가장 큰 차이점은 cache의 사용 여부

1. Statement
 - 쿼리분석 / 컴파일 / 실행
 - 실행할 때마다 3단계를 거친 후 작동
 - 매번 컴파일 = 성능상 이슈 존재
String str = "SELECT name, empNo FROM TEMP02 WHERE empNo"+empNo
Statement stmt = conn.credateStatement();
ResultSet rs = stmt.executeQuery(str);
cs
str 실행 시 결과 값을 생성


2. PreparedStatement
 - 쿼리분석 / 컴파일 / 실행
 - 3단계를 처음 1번 실행한 후 cache에 담아서 재사용
 - 컴파일이 미리 되어 있기에 재사용성이 높음
 - ? 부분만 변화를 주어 지속적으로 SQL문을 수행 = 가독성은 떨어짐
String str = "SELECT name, empNo FROM TEMP02 WHERE empNo = ?"
PreparedStatement pstmt = conn.prepareStatement (str);
pstmt.setInt(1, empNo);
ResultSet prs = pstmt.executeQuery();
cs
str은 생성할 때 실행

3. API
Statement

1) Statement 오브젝트마다 1개의 ResultSet이 오픈됨
2) 실행 중인 ResultSet의 read()외에 다른 read()가 존재한다면 그것은 다른 ResultSet의 것
     = 다른 Statement 오브젝트에 의해 생성된 것
3) Statement의 execution은 이미 실행 중인 ResultSet이 있다면 암묵적으로 종료시킴



PreparedStatement

1) Statement를 상속받음
2) SQL문은 먼저 컴파일되어 PreparedStatement 오브젝트 내에 저장됨


4. 사용
1) statement
String str     = null;
Statement stmt = null;
ResultSet rs   = nul;
 
for(int i = 0; i < 100; i++){
    str  = "SELECT name, empNo FROM TEMP03 WHERE empNo"+empNo
    stmt = conn.credateStatement();
    rs   = stmt.executeQuery(str);
}
cs

2)preparedStatement
String str = null
PreparedStatement pstmt = null
ResultSet prs = null
 
str   = "SELECT name, empNo FROM TEMP03 WHERE empNo = ?"
pstmt = conn.prepareStatement(str); 
 
for(int i = 0; i < 100; i++){
    pstmt.setIn(1, i);
    prs = pstmt.executeQuery();
}
cs

4-1. 의미없는 이야기: 반복문을 사용할 때는 주로 statement 구문을 사용