JDBC :: Statement / PreparedStatement / '?'
Statement / Prepared Statement
둘 모두 SQL문을 실행할 수 있는 객체이며, 가장 큰 차이점은 캐시 사용 여부이다.
Statement를 사용하면 매번 쿼리를 수행할 때마다 계속적으로 단계를 거치면서 수행하지만 PreparedStatement는 처음 한 번만 세 단계를 거친 후 캐시에 담아 재사용을 한다. 만약 동일한 쿼리를 반복적으로 수행한다면 PrepardStatement가 DB에 훨씬 적은 부하를 주며, 성능도 좋다.
Statement
1. 쿼리문을 수행할 때마다 SQL 실행단계 1~3 단계를 거침
2. SQL 문을 수행하는 과정에서 매번 컴파일을 하기 때문에 성능상 이슈 발생
3. 실행되는 SQL문을 확인 가능
Prepared Statement
1. 컴파일이 미리 되어있기 때문에 Statement에 비해 좋은 성능
2. 특수문자를 자동으로 파싱해주기 때문에 SQL injection 같은 공격을 막을 수 있음
3. "?" 부분에만 변화를 주어 쿼리문을 수행하므로 실행되는 SQL문을 파악하기 어려움
?
물음표(?)는 PreparedStatement에서 사용되는 매개변수(파라미터)이다. 실제 실행 시에는 해당 위치에 매개변수 값을 설정할 수 있다. 이를 통해 SQL 쿼리를 동적으로 생성하고 실행할 수 있으며, SQL 쿼리의 재사용성과 보안성을 향상시킬 수 있다.
아래의 코드에서 SELECT * FROM emp WHERE empno >= ? 쿼리에서 물음표는 empno >= ? 부분에 해당한다. 여기서 ?는 직원 코드가 어떤 값을 가지는지는 실행 시에 설정되고, 이를 통해 다양한 조건으로 쿼리를 실행할 수 있다.
EMP 테이블에서 직원 번호가 10 이상인 직원 조회하는 코드
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
// JDBC 연결 정보
String url = "jdbc:mysql://localhost:3306/your_database_name";
String username = "your_username";
String password = "your_password";
// JDBC 연결 객체 초기화
try (Connection conn = DriverManager.getConnection(url, username, password)) {
// SQL 쿼리 작성
String sql = "SELECT * FROM emp WHERE empno >= ?";
// PreparedStatement 객체 생성
PreparedStatement pstmt = conn.prepareStatement(sql);
// 파라미터 설정
pstmt.setInt(1, 10); // 직원 코드가 10 이상인 경우
// 쿼리 실행 및 결과 조회
ResultSet rs = pstmt.executeQuery();
// 결과 출력
while (rs.next()) {
System.out.println("Empno: " + rs.getInt("empno"));
System.out.println("Ename: " + rs.getString("ename"));
// 필요한 다른 컬럼들도 출력 가능
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}