Statement와 PreparedStatement
Statement
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM users WHERE id = 1");
Statement는 JDBC에서 제공하는 가장 기본적인 쿼리 실행 방식이다. 이는 데이터베이스에 SQL 문을 전달하고 실행하는 단순한 인터페이스를 제공한다.
Statement를 사용할 때마다 데이터베이스는 SQL 문을 파싱하고, 컴파일하여 실행 계획을 생성한다. 이러한 과정은 매 실행마다 반복되며, 불필요한 작업이다.
Statement의 실행 과정은 크게 네 단계로 나눌 수 있다.
- SQL 문장이 데이터베이스 서버로 전송
- 데이터베이스 서버는 받은 SQL 문장을 파싱하여 문법적 오류를 검사
- 실행 계획 생성
- 결과 반환
즉, Statement를 이용한 쿼리 실행 방식은 캐시를 사용하지 않으며, 매번 SQL 구문을 파싱하고 실행 계획을 새로 생성한다.
PreparedStatement
PreparedStatement pstmt = connection.prepareStatement(
"SELECT * FROM users WHERE id = ?"
);
pstmt.setInt(1, userId);
ResultSet rs = pstmt.executeQuery();
PreparedStatement는 Statement의 한계를 극복하기 위해 개발된 향상된 기능이다. 가장 큰 특징은 이미 실행한 SQL 문을 미리 컴파일하여 저장한다는 점이다.
이는 동일한 쿼리를 반복 실행할 때 매우 효율적으로 나타난다. PreparedStatement는 플레이스홀더(?)를 사용하여 값을 동적으로 바인딩할 수 있게 해주며, SQL 인젝션 공격을 예방하는 데도 도움이 된다.
PreparedStatement의 실행 과정은 처음 쿼리를 실행할 때에는 Statement와 동일하지만, 이미 실행한 쿼리에 대해서는 Statement와 다르게 두 단계로 나뉜다.
- SQL 문이 데이터베이스에 전송되어 파싱, 컴파일되고 실행 계획이 생성, 이 단계는 PreparedStatement가 처음 생성될 때 한 번만 수행
- 준비된 쿼리에 실제 값(파라미터)을 바인딩하고 실행, 이 단계는 동일한 PreparedStatement를 재사용할 때마다 수행
즉, PreparedStatement는 SQL 문을 미리 컴파일하여 캐시에 저장함으로써 반복 실행 시 성능을 향상시키고 바인드 변수를 통해 SQL 인젝션을 방지하는 향상된 쿼리 실행 방식이다.
Statement가 캐시를 사용하지 않는 이유
Statement는 쿼리를 날릴 때 바인드 변수를 사용하는게 아닌 쿼리 안에 변수를 넣어서 데이터베이스로 요청을 보내게 된다. 이에 데이터베이스가 쿼리를 수행하면서 생성된 실행계획을 라이브러리 캐시에 보관하게 되는데, 이때, 라이브러리 캐시에서 SQL을 찾기위해 사용하는 키 값이 "SQL문 그 자체" 인데, 한 부분이라도 다르다면 키 값이 달라져서 캐시된 값을 찾지 못한다.
반면에 PreparedStatement는 바인드 변수를 사용하여 SQL 문장의 구조는 동일하게 유지하면서 값만 변경할 수 있다. 이렇게 하면 SQL 문장의 구조가 동일하기 때문에 라이브러리 캐시에서 동일한 키 값으로 실행 계획을 찾을 수 있어 매번 새로운 파싱과 컴파일 과정을 거치지 않고 캐시된 실행 계획을 재사용할 수 있다.
참고
[JDBC] Statement vs. PreparedStatement
[JDBC] Statement vs. PreparedStatement
`Statement`는 DB에 쿼리를 보내 실행시키는 객체이다. `PreparedStatement`는 `Statement`를 상속받은 객체로, 확장된 기능을 가지고 있어 더 자주 사용되지만 `Statement`를 완전히 대체할 수 있는 것은 아니다
velog.io
[JDBC] Statement vs. PreparedStatement Statement 대신 preparedStatement 사용하는 이유 :: codemon
Statement 대신 preparedStatement 사용하는 이유
이유는 Statement 객체에서 사용한 createStatement()라는 메소드 때문입니다. 이것을 사용할 경우 사용자의 입력 값을 미리 만들어 놓은 sql문에 적용한 후 컴파일을 하기 때문에 사용자의 입력 값에 따
oper6210.tistory.com