본문 바로가기
Language/Java

[Java] PreparedStatement 공부하기

by SooooooooS 2024. 4. 28.
728x90
회사 과제를 진행하며 pstmt를 사용해 좀 더 효율적인 insert 작업을 수행해야 했다.
다른 사람의 코드를 참고하면서 어느 정도는 알았지만 활용하기 위해 기초를 정리해본다.

1. 공식문서

PreparedStatement 공식문서

 

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. 특징

  1. 미리 컴파일
    1. SQL문을 미리 컴파일하여 캐싱
    2. 동일한 쿼리를 반복적으로 실행할 때 성능 향상
  2. 매개변수화된 입력
    1. SQL 쿼리에 매개변수를 사용하고 이 는 setX() 메서드를 사용하여 동적으로 설정
    2. 동적 데이터를 안전하게 SQL 문에 바인딩
  3. 보안
    1. 매개변수를 통해 입력을 전달하므로 SQL Injection 공격을 방지
  4. 가독성과 유지보수성
    1. 매개변수화된 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();
}
  1. 실행할 Query를 작성한다.
    • '?'를 사용해 동적으로 값을 설정할 매개변수의 위치를 지정
  2. pstmt를 설정한다.
    • 데이터베이스 연결 및 실행할 쿼리를 지정
  3. 매개변수에 값 바인딩한다.
    • Query를 작성할 때 쓰였던 ? 위치에 동적으로 값을 바인딩한다.
    • 물음표의 개수에 따라 1번부터 매개변수를 셋팅한다.
    • setX(index, value) 메소드를 사용한다.
  4. 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

'Language > Java' 카테고리의 다른 글

[Java] MacOS JDK 삭제  (2) 2023.11.27
[Java] Type & BigInteger  (0) 2023.11.02