[Java] 자바 이클립스 JDBC 5. Statement와 PreparedStatement 비교



Statement와 PreparedStatement의 차이

1) 보안

    Statement: 

    - 사용자가 입력한 값을 가지고 SQL문을 만들기 때문에 보안이 취약하다.

    - 즉 악의적으로 SQL의 일부를 포함하는 값을 입력할 수 있다.

    PreparedStatement

    - ?(in-parameter) 자리에 임의의 SQL문을 삽입할 수 없다.

    - 삽입해봐야 단순 문자열로 취급한다.

    - 그래서 보안 문제를 발생시키지 않는다.

2) 바이너리 데이터

    Statement

    - 문자열로 SQL문을 만들기 때문에 바이너리 데이터를 삽입할 수 없다.

    PreparedStatement

    - ?(in-parameter) 자리에 바이너리 데이터를 삽입할 수 있다.

3) 코드의 가독성

    Statement

    - + 연산자를 사용하여 컬럼의 값을 연결하는 식으로 문자열을 만들기 때문에,

      컬럼의 개수가 많으면 문자열을 붙이는 코드도 산만해지고 복잡해진다.

    PreparedStatement

    - setXxx()를 사용하여 값을 넣기 때문에 코드가 간결하다.

4) 실행속도

    서버에 SQL문을 전달하기 전에 서버에서 원하는 형식으로 변환하여 보낸다.

    단순히 SQL을 한 번만 실행한다면 Statement나 PreparedStatement 둘 다 속도가 같다.

    그러나 같은 SQL문을 값을 바꿔가면서 여러 번 실행할 경우,

    PreparedStatement는 SQL문을 컴파일한 후 값만 넣어서 보내기 때문에 속도가 빠르다.

   Statement는 executeXxx()를 실행할 때마다 SQL문을 매번 컴파일하기 때문에 속도가 느리다.

      



JDBC 프로그래밍: PreparedStatement 객체 사용 후

 - 더하기 연산자를 사용하여 SQL문을 만드는 대신,

   in-parameter '?' 를 사용하여 SQL 문을 만든다.



JDBC SQL에서 PreparedStatement의 사용 예제


import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test05_2 {
  public static void main(String[] args) throws Exception {
    // 원래는 값을 JVM 아규먼트나 프로그램 아규먼트 등 외부로부터 받아야 하지만,
    // 테스트를 원활하게 하기 위해서 변수에 값을 담아 놓자!
   
    String jdbcDriver = "com.mysql.jdbc.Driver";
    String jdbcUrl = "jdbc:mysql://localhost:3306/데이터베이스명";
    String jdbcUsername = "유저명";
    String jdbcPassword = "1111";
   
    String name = "홍길동102";
    String email = "hong102@test.com";
    String tel = "1111-1111";
    String password = "1111";
    try {
      Class.forName(jdbcDriver);
    } catch (Exception e) {
      e.printStackTrace();
    }
   
    try (
      Connection con = DriverManager.getConnection(jdbcUrl, jdbcUsername,jdbcPassword);
       
      // SQL 문을 미리 작성해둔다. 값(문자, 숫자 상관없이)이 들어갈 자리는 ?을 사용하여 비워둔다.
      // 이때 ?를 in-parameter라 부른다.
      // preparedStatement()의 리턴 값은 java.sql.PreparedStatement의 구현체이다.
    PreparedStatement stmt = con.prepareStatement("insert into memb(name, tel, email, pwd) values(?,?,?,password(?))");
    ) {
     
    // SQL문을 서버에 보내기 전에 in-parameter 자리에 값을 채운다.
    // 컬럼의 타입에 따라 호출하는 메서드가 다르다.
    // => setXxx(컬럼인덱스, 값)
    // => 컬럼 인덱스는 1부터 시작한다.
    // 빈자리(in-parameter)에 값을 넣을 때 컬럼의 순서를 지킬 필요는 없다.
    // 그렇다고 굳이 임의 순서대로 넣는 것은 코드의 이해도를 떨어뜨린다.
    stmt.setString(1, name);
    stmt.setString(2,  tel);
    stmt.setString(3, email);
    stmt. setString(4, password);
    // 이렇게 setXxx()를 호출하여 SQL 문을 완성하면,
    // + 연산자를 사용하여 SQL문을 완성하는 방법보다 편리하고 가독성이 좋다.
   
    // 위에서 SQL문을 준비하고 값을 채웠기 때문에 여기에서는 그냥 실행만 하면 된다.
   
    int count = stmt.executeUpdate("insert into memb(name, tel, email, pwd) values('" +
      name + "', '"+
      tel + "', '"+
      email + "', password('" +
      password + "'))");
     
    System.out.println(count);
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}



블로그 이미지

필로그래머

,