Language/Java
[Java] PreparedStatement 공부하기
SooooooooS
2024. 4. 28. 17:03
728x90
회사 과제를 진행하며 pstmt를 사용해 좀 더 효율적인 insert 작업을 수행해야 했다.
다른 사람의 코드를 참고하면서 어느 정도는 알았지만 활용하기 위해 기초를 정리해본다.
1. 공식문서
PreparedStatement (Java Platform SE 8 )
Sets the designated parameter to SQL NULL. This version of the method setNull should be used for user-defined types and REF type parameters. Examples of user-defined types include: STRUCT, DISTINCT, JAVA_OBJECT, and named array types. Note: To be portable,
docs.oracle.com
2. 정의
- Java에서 PreparedStatement는 SQL 문을 실행하기 위한 인터페이스로, Statement의 확장된 형태
PreparedStatement는 SQL 쿼리를 미리 컴파일하여 캐싱하고, 이후에 매개변수화된 입력 값들을 쉽게 바인딩하여 실행할 수 있도록 도와줍니다. 이는 SQL Injection 공격을 방지하고 성능을 향상시키는 데 도움이 됩니다.
3. 특징
- 미리 컴파일
- SQL문을 미리 컴파일하여 캐싱
- 동일한 쿼리를 반복적으로 실행할 때 성능 향상
- 매개변수화된 입력
- SQL 쿼리에 매개변수를 사용하고 이 는 setX() 메서드를 사용하여 동적으로 설정
- 동적 데이터를 안전하게 SQL 문에 바인딩
- 보안
- 매개변수를 통해 입력을 전달하므로 SQL Injection 공격을 방지
- 가독성과 유지보수성
- 매개변수화된 SQL 쿼리는 가독성이 높아지므로 유지보수가 쉽다.
4. 기본 코드 예시
// 1. 실행할 SQL문 작성
String sql = "SELECT * FROM users WHERE username = ?";
// DB 연결
try (Connection conn = DriverManager.getConnection(url, username, password);
// 2. pstmt 설정
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 3. 매개변수 설정
pstmt.setString(1, "exampleUsername");
// 4. 쿼리 실행
ResultSet rs = pstmt.executeQuery();
// 결과 처리
while (rs.next()) {
// 결과 읽기
String username = rs.getString("username");
}
} catch (SQLException e) {
e.printStackTrace();
}
- 실행할 Query를 작성한다.
- '?'를 사용해 동적으로 값을 설정할 매개변수의 위치를 지정
- pstmt를 설정한다.
- 데이터베이스 연결 및 실행할 쿼리를 지정
- 매개변수에 값 바인딩한다.
- Query를 작성할 때 쓰였던 ? 위치에 동적으로 값을 바인딩한다.
- 물음표의 개수에 따라 1번부터 매개변수를 셋팅한다.
- setX(index, value) 메소드를 사용한다.
- Query를 실행한다.
- executeQuery()를 통해 실행
- 실행된 Query의 결과는 ResultSet 으로 받을 수 있다.
5. 과제 활용 내용 (addBatch)
목표 : 약 1만건의 데이터를 삽입
▶ 하나씩 처리
하나의 쿼리를 작성하고 이를 동적으로 바인딩 후 실행
PreparedStatement pstmt = null;
String insertQuery = "INSERT INTO TEST (ID, CRAT_DTM) VALUES (?, ?)";
try {
pstmt = getConnection().prepareStatement(insertQuery);
String t;
while((t = br.readLine()) != null) {
String[] tmp = t.split(",");
// 매개변수에 값 삽입
for(int i = 0; i < tmp.length; i++) {
pstmt.setString(i, tmp[i]);
}
// 하나의 쿼리문 실행하기
pstmt.executeUpdate();
}
} catch (SQLException e) {
// 예외 처리
} finally {
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
// 예외 처리
}
}
}
위와 같이 작성하고 실행하니 약 7~8초 정도의 시간이 걸렸다.
반복문이 실행되는 동안 계속 데이터베이스와 연결하여 트랜잭션을 발생시킨다.
▶ 통합 처리
하나의 쿼리에 동적으로 바인딩하여 이를 쌓은 후 실행
PreparedStatement pstmt = null;
String insertQuery = "INSERT INTO TEST (ID, CRAT_DTM) VALUES (?, ?)";
try {
pstmt = getConnection().prepareStatement(insertQuery);
String t;
while((t = br.readLine()) != null) {
String[] tmp = t.split(",");
// 매개변수 값 설정하기
for(int i = 0; i < tmp.length; i++) {
pstmt.setString(i, tmp[i]);
}
// 쿼리문 쌓기
pstmt.addBatch();
}
// 쌓인 쿼리문 실행하기
pstmt.executeBatch();
} catch (SQLException e) {
// 예외 처리
} finally {
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
// 예외 처리
}
}
}
위와 같이 작성하고 실행하니 약 1~2초 정도의 시간이 걸렸다.
반복문이 도는 동안 쿼리만 작성해두고 끝난 후 한 번 트랜잭션을 발생시킨다.
728x90