Statement와 PreparedStatement의 차이
Statement
- 단일로 사용될 때 속도가 빠르다.
- 쿼리에 인자를 부여할 수 없다.
- 매번 컴파일을 수행해야 한다.
PreparedStatement
- 여러 번 수행될 때 속도가 빠르다.
- 쿼리에 인자를 부여할 수 있다.
- 처음 컴파일된 이후에는 컴파일을 다시 수행하지 않는다.
- Statement 클래스보다 기능이 향상된 클래스로, 코드의 안정성과 가독성이 높다.
Statement보다 PreparedStatement를 사용하는 것을 권장한다.
UPDATE문 작성 (Statement)
package day03;
import java.sql.*;
import java.util.Scanner;
/*
* Statement를 이용하여
* java_member테이블의 회원정보를 수정해봅시다
* */
public class StatementTest1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("수정할 회원의 ID 입력: ");
String id = sc.nextLine();
System.out.println("수정할 회원의 Name 입력: ");
String name = sc.nextLine();
System.out.println("수정할 회원의 Tel 입력: ");
String tel = sc.nextLine();
System.out.println("수정할 회원의 PW 입력: ");
String pw = sc.nextLine();
System.out.println(id+"/"+name+"/"+tel+"/"+pw);
try {
//1. driver 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
System.out.println("driver 클래스 로딩 성공!");
//2. db 연동
String user = "scott", password = "tiger";
String url = "jdbc:oracle:thin:@localhost:1521:XE";
Connection con = DriverManager.getConnection(url, user, password);
System.out.println("db연동 성공!");
//3. SQL문 작성
String sql = "UPDATE java_member SET name='" + name + "', tel='"
+ tel + "', pw=" + pw + " WHERE id = '" + id + "'";
System.out.println(sql);
//4. Statement 객체 얻기
Statement stmt = con.createStatement();
//5. execute 쿼리 실행
boolean b = stmt.execute(sql);
System.out.println("b: " + b);
//ResultSet 객체가 아니므로 false 반환
//6. executeUpdate 쿼리 실행
int re = stmt.executeUpdate(sql);
System.out.println(re + "개 레코드 수정 완료!");
//7.db자원 반납
stmt.close();
con.close();
} catch(ClassNotFoundException e){
e.printStackTrace();
} catch(SQLException e) {
e.printStackTrace();
}
}
}
UPDATE문 작성 (PreparedStatement)
package day03;
import java.sql.*;
import java.util.Scanner;
/*
* PreparedStatement를 이용하여
* java_member테이블의 회원정보를 수정해봅시다
* */
public class PreparedStatementTest1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("수정할 회원의 ID 입력: ");
String id = sc.nextLine();
System.out.println("수정할 회원의 Name 입력: ");
String name = sc.nextLine();
System.out.println("수정할 회원의 Tel 입력: ");
String tel = sc.nextLine();
System.out.println("수정할 회원의 PW 입력: ");
String pw = sc.nextLine();
System.out.println(id+"/"+name+"/"+tel+"/"+pw);
try {
//1. driver 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
System.out.println("driver 클래스 로딩 성공!");
//2. db 연동
String user = "scott", password = "tiger";
String url = "jdbc:oracle:thin:@localhost:1521:XE";
Connection con = DriverManager.getConnection(url, user, password);
System.out.println("db연동 성공!");
//3. SQL문 작성
//PreparedStatement 이용시에는 값에 해당하는 부분을 ? (in parameter)로 기술
String sql = "UPDATE java_member SET name=?, tel=?, pw=? WHERE id=?";
System.out.println(sql);
//4. PreparedStatement 객체 얻기
PreparedStatement pstmt = con.prepareStatement(sql);
//5. PreparedStatement의 set 메서드를 사용하여 필요한 값을 지정
//PreparedStatement 객체를 생성한 다음에는 PreparedStatement가 제공하는
//set계열의 메서드를 사용하여 ? 를 대체할 값을 지정해 주어야 한다.
//앞의 숫자는 ?의 순서이다.
pstmt.setString(1, name);
pstmt.setString(2, tel);
pstmt.setString(3, pw);
pstmt.setString(4, id);
//6. execute 쿼리 실행
boolean b = pstmt.execute();
System.out.println("b: " + b);
//ResultSet 객체가 아니므로 false 반환
//7. executeUpdate 쿼리 실행
int re = pstmt.executeUpdate();
System.out.println(re + "개 레코드 수정 완료!");
//8. db자원 반납
pstmt.close();
con.close();
} catch(ClassNotFoundException e){
e.printStackTrace();
} catch(SQLException e) {
e.printStackTrace();
}
}
}
예제를 통한 Statement와 PreparedStatement의 차이
1. 완성된 SQL문 vs 미완성된 SQL문
//<Statement>
//3. SQL문 작성
String sql = "UPDATE java_member SET name='" + name + "', tel='"
+ tel + "', pw=" + pw + " WHERE id = '" + id + "'";
//<PreparedStatement>
//3. SQL문 작성
String sql = "UPDATE java_member SET name=?, tel=?, pw=? WHERE id=?";
- Statement는 변수나 값을 넣을 때 + 를 사용해야 돼서 가독성이 낮고, 코드의 길이가 길어진다.
반면, PreparedStatement는 변수나 값에 해당하는 부분에 ? (in parameter)를 사용하므로 가독성이 높고, 코드의 길이가 짧다. - Statement의 SQL문은 완성된 SQL문인 반면, PreparedStatement의 SQL문은 미완성된 SQL문이다.
PreparedStatement는 추후에 미완성 SQL문에 인자를 setString()으로 전달해야 한다.
2. 객체 생성
//<Statement>
//4. Statement 객체 얻기
Statement stmt = con.createStatement();
//<PreparedStatement>
//4. PreparedStatement 객체 얻기
PreparedStatement pstmt = con.prepareStatement(sql);
- Statement는 객체 생성시 createStatement 메서드를 호출하고, 인자값이 없다.
- PreparedStatement는 객체 생성시 prepareStatement 메서드를 호출하며, 인자값으로 미완성된 sql문이 전달된다.
3. Excute 쿼리 실행 전 - PreparedStatement
//<PreparedStatement>
//5. PreparedStatement의 set 메서드를 사용하여 필요한 값을 지정
//PreparedStatement 객체를 생성한 다음에는 PreparedStatement가 제공하는
//set계열의 메서드를 사용하여 ? 를 대체할 값을 지정해 주어야 한다.
//앞의 숫자는 ?의 순서이다.
pstmt.setString(1, name);
pstmt.setString(2, tel);
pstmt.setString(3, pw);
pstmt.setString(4, id);
- SQL문 실행 전에 미완성된 문장을 PreparedStatement 클래스의 set 메서드로 채워준다.
- PreparedStatement 객체를 생성한 다음에는 PreparedStatement가 제공하는 set 계열의 메서드를 사용하여 ? 를 대체할 값을 지정해 주어야 한다.
- 앞의 숫자(1, 2, 3, 4)는 ?의 순서이다.
- pstmt.setXXX(?의 위치, 실제값)
4. Excute 메서드 차이
//<Statement>
//5. execute 쿼리 실행
boolean b = stmt.execute(sql);
System.out.println("b: " + b);
//ResultSet 객체가 아니므로 false 반환
//6. executeUpdate 쿼리 실행
int re = stmt.executeUpdate(sql);
System.out.println(re + "개 레코드 수정 완료!");
//<PreparedStatement>
//6. execute 쿼리 실행
boolean b = pstmt.execute();
System.out.println("b: " + b);
//ResultSet 객체가 아니므로 false 반환
//7. executeUpdate 쿼리 실행
int re = pstmt.executeUpdate();
System.out.println(re + "개 레코드 수정 완료!");
- Statement 클래스를 통한 SQL문 실행시 execute 메서드의 인자값으로 sql문을 전달한다.
- PreparedStatement 클래스를 통해 SQL문을 실행하면 execute 메서드의 인자값은 비워둔다.
정리
Statement | PreparedStatement |
완성된 SQL문 String sql = " + " |
미완성된 SQL문 String sql = " ?, ?, ? " |
객체 생성시 createStatement 메서드 호출 (인자값 없음) Statement stmt = con.createStatement(); |
객체 생성시 prepareStatement 메서드 호출 (미완성된 sql을 인자값으로 전달) PreparedStatement pstmt = con.prepareStatememt(sql); |
Statement 객체를 통한 SQL문 실행시 execute 메서드의 인자값으로 sql문 전달 stmt.executeXXX(sql); |
SQL문 실행 이전, 미완성된 sql을 PreparedStatement 클래스의 set 메서드로 채워줌 pstmt.setString(?의 위치, 실제값) pstmt.setInt(?의 위치, 실제값) PreparedStatement 객체를 통한 SQL문 실행시 execute 메서드의 인자값으로 sql문을 전달하지 않음 pstmt.executeXXX(); |