쿼리문을 생성할 때 Statement 혹은 PreparedStatement를 사용하는데
차이가 무엇인지 각각 알아보자
먼저 Statement를 사용해서 조회할 경우인데
package db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
public class ConnectionTest {
public static void main(String[] args) {
try {
Class.forName("oracle.jdbc.driver.OracleDriver"); // 드라이버 로딩
System.out.println("드라이버 로딩 성공..");
String sql = "SELECT * FROM TEST_TABLE WHERE NAME = 'KIM'"; // SELECT Query
String url = "jdbc:oracle:thin:localhost:1521:SID";
String id = "scott"; // 접속 ID
String pass = "tiger"; // 접속 PW
Connection conn = DriverManager.getConnection(url,id,pass); // 드라이버 접속
System.out.println("드라이버 접속 성공!");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql); // SELECT 한 내용 RS에 넣기
while(rs.next()) { // ResultSet에 다음 값이 없을때까지 출력
String name = rs.getString("NAME"); // 컬럼 값 받아오기
int val = rs.getInt("VAL");
System.out.println("NAME : " + name + " VAL : " + val);
}
// 연결 끊기
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
여기서 포인트는
Statement stmt = conn.createStatement()
ResultSet rs = stmt.executeQuery(sql);
이 부분인데
createStatement 메소드에 파라미터가 없고
executeQuery(sql) 메소드에 쿼리를 파라미터로 넣기 때문에
실행 전까지는 무슨 쿼리를 실행하는지 알지 못한다
(만들때 쿼리를 알려주지 않았으니!!)
따라서 쿼리문을 실행할 때마다 생성하며 반복 실행되는 경우에는 효율이 떨어진다!!!
여기에 추가로 쿼리문을 프로그램 외부에서 작성한 뒤
내부에서 실행하는 SQL Injection 공격에 취약한데
포트폴리오나 만드는 초보 수준에는 SQL Injection 공격을 당하고 싶어도
당할 수가 없으니 SQL Injection 공격에 대한 설명은 이후에 하도록 한다
다음으로 PreparedStatement에 알아보자
package db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
public class ConnectionTest {
public static void main(String[] args) {
try {
Class.forName("oracle.jdbc.driver.OracleDriver"); // 드라이버 로딩
System.out.println("드라이버 로딩 성공..");
String sql = "SELECT * FROM TEST_TABLE WHERE NAME = ?"; // SELECT Query
String url = "jdbc:oracle:thin:localhost:1521:SID";
String id = "scott"; // 접속 ID
String pass = "tiger"; // 접속 PW
Connection conn = DriverManager.getConnection(url,id,pass); // 드라이버 접속
System.out.println("드라이버 접속 성공!");
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, "KIM");
ResultSet rs = stmt.executeQuery(); // SELECT 한 내용 RS에 넣기
while(rs.next()) { // ResultSet에 다음 값이 없을때까지 출력
String name = rs.getString("NAME"); // 컬럼 값 받아오기
int val = rs.getInt("VAL");
System.out.println("NAME : " + name + " VAL : " + val);
}
// 연결 끊기
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
여기서 포인트는
String sql = "SELECT * FROM TEST_TABLE WHERE NAME = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, "KIM");
ResultSet rs = stmt.executeQuery();
이렇게 4줄인데
쿼리를 써 놓은 부분에 ?가 생긴 것이 보인다
이것을 Bind 변수라고 하는데
setString, setInt을 통해 값을 가변적으로 바꿔줄 때 사용하는 것이다
setString(?순서, "들어갈 값");
이런 식으로 사용한다
그리고
PreparedStatement stmt = conn.prepareStatement(sql);
부분에서 Statement를 떠올려보면
Statement stmt = conn.createStatement()
였던 것이 떠오르는데
Statement는 쿼리문을 미리 생성하지 않으나
PreparedStatement는 쿼리문을 미리 생성한다!!!
그래서
ResultSet rs = stmt.executeQuery();
이렇게 출력 결과를 받아올 때에 쿼리를 파라미터에 넣지 않고 수행하는 것이 보인다
이런 방식으로 사용하면 실행시마다 쿼리를 생성하지 않기 때문에
Statement에 비해 반복실행시 속도가 훨씬 빠르다
정리해보자면
Statement는
쿼리문을 실행할 때 생성하며
---
Statement stmt = conn.createStatement()
ResultSet rs = stmt.executeQuery(sql);
---
반복 실행시 효율이 떨어지고
SQL Injection 공격에 취약하다!!
PreparedStatement는
쿼리문을 미리 생성하고
---
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
---
bind 변수를 사용하고
---
String sql = "SELECT * FROM TEST_TABLE WHERE NAME = ?";
stmt.setString(1, "KIM");
---
SQL Injection이 발생하지 않고
반복실행시 속도가 Statement 보다 훨씬 빠르다!!
'IT > Java' 카테고리의 다른 글
자바 break, continue 차이 알아보기 (0) | 2019.06.20 |
---|---|
자바 AWT로 화면 만들기 (0) | 2019.05.21 |
자바 JDBC로 CRUD 해보기 (1) | 2019.05.13 |
자바 JDBC 연결해 출력하기 (0) | 2019.05.12 |
카멜 케이스(Camel case) 표기법 알아보기 (0) | 2019.03.14 |
댓글