본문 바로가기
IT/Java

Statement PreparedStatement 차이 알아보기

by flatsun 2019. 5. 15.
반응형

쿼리문을 생성할 때 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

댓글