Computer >> 컴퓨터 >  >> 프로그래밍 >> MySQL

JDBC PreparedStatement란 무엇인가? 개념부터 실행까지 완벽 정리


PreparedStatement 인터페이스는 Statement 인터페이스를 확장한 것으로, 한 번 컴파일한 뒤 여러 번 실행할 수 있는 사전 컴파일(precompiled)된 SQL 문을 나타냅니다. 이 인터페이스는 매개변수화된(parameterized) SQL 쿼리를 지원하며, 쿼리에 0개 이상의 매개변수를 전달할 수 있습니다.

처음에는 실제 값 대신 물음표("?") 형태의 플레이스홀더(placeholder)를 사용하고, 이후 PreparedStatement 인터페이스가 제공하는 setXXX() 메서드를 통해 해당 자리에 값을 동적으로 지정하게 됩니다.

PreparedStatement의 주요 장점

  • 성능 향상: 쿼리가 한 번만 컴파일되므로, 동일한 쿼리를 반복 실행할 때 일반 Statement보다 훨씬 효율적입니다.

  • SQL 인젝션 방지: 값이 쿼리 문자열과 분리되어 전달되기 때문에 악의적인 입력으로 인한 SQL 인젝션 공격에 강합니다.

  • 코드 가독성: 파라미터화된 쿼리 덕분에 복잡한 문자열 연결 없이 깔끔한 코드를 작성할 수 있습니다.

PreparedStatement 생성하기

PreparedStatement 객체는 Connection 인터페이스의 prepareStatement() 메서드를 통해 생성할 수 있습니다. 이 메서드는 매개변수화된 쿼리를 인자로 받아 PreparedStatement 객체를 반환합니다.

이 메서드를 호출하면 Connection 객체가 해당 쿼리를 데이터베이스로 전송하여 컴파일하고 저장합니다. 쿼리가 정상적으로 컴파일된 경우에만 객체가 반환됩니다.

쿼리를 컴파일하는 시점에는 실제 값이 필요하지 않기 때문에, 값이 들어갈 자리에 0개 이상의 플레이스홀더(물음표 "?")를 사용할 수 있습니다.

예를 들어, 데이터베이스에 다음 쿼리로 생성된 Employee 테이블이 있다고 가정해 보겠습니다.

CREATE TABLE Employee(Name VARCHAR(255), Salary INT NOT NULL, Location VARCHAR(255));

그러면 아래와 같이 PreparedStatement를 사용해 이 테이블에 값을 삽입할 수 있습니다.

// PreparedStatement 생성
String query = "INSERT INTO Employee(Name, Salary, Location) VALUES(?, ?, ?)";
PreparedStatement pstmt = con.prepareStatement(query);

플레이스홀더에 값 설정하기

PreparedStatement 인터페이스는 setInt(), setFloat(), setArray(), setDate(), setDouble() 등 다양한 setter 메서드를 제공하여, 준비된 문장의 플레이스홀더에 값을 설정할 수 있게 해줍니다.

이 메서드들은 두 개의 인자를 받습니다. 하나는 플레이스홀더의 위치를 나타내는 정수 인덱스이고, 다른 하나는 해당 위치에 삽입할 값(int, String, float 등)입니다.

앞서 생성한 문장의 플레이스홀더에 setter 메서드로 값을 설정하는 방법은 다음과 같습니다.

pstmt.setString(1, "Amit");
pstmt.setInt(2, 3000);
pstmt.setString(3, "Hyderabad");

pstmt.setString(1, "Kalyan");
pstmt.setInt(2, 4000);
pstmt.setString(3, "Vishakhapatnam");

pstmt.setString(1, "Renuka");
pstmt.setInt(2, 5000);
pstmt.setString(3, "Delhi");

pstmt.setString(1, "Archana");
pstmt.setInt(2, 15000);
pstmt.setString(3, "Mumbai");

PreparedStatement 실행하기

PreparedStatement 객체를 생성한 후에는 PreparedStatement 인터페이스의 execute(), executeUpdate(), executeQuery() 메서드 중 하나를 사용해 실행할 수 있습니다.

  • execute(): 현재 준비된 문장 객체에서 일반적인 정적 SQL 문을 실행하고 boolean 값을 반환합니다.

  • executeQuery(): 현재 준비된 문장을 실행하고 ResultSet 객체를 반환합니다. 주로 SELECT 문에 사용됩니다.

  • executeUpdate(): INSERT, UPDATE, DELETE 같은 SQL DML 문을 실행하고, 영향을 받은 행의 수를 나타내는 정수를 반환합니다.

예제

다음 예제에서는 PreparedStatement를 사용하여 Employees 테이블에 여러 건의 데이터를 삽입해 보겠습니다. 각 레코드의 값을 설정한 뒤 executeUpdate()를 호출하면 됩니다.

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class PreparedStatementExample {
    public static void main(String args[]) throws SQLException {
        // 드라이버 등록
        DriverManager.registerDriver(new com.mysql.jdbc.Driver());

        // 데이터베이스 연결
        String mysqlUrl = "jdbc:mysql://localhost/testdb";
        Connection con = DriverManager.getConnection(mysqlUrl, "root", "password");
        System.out.println("연결이 설정되었습니다......");

        // PreparedStatement 생성
        String query = "INSERT INTO Employees(Name, Salary, Location) VALUES (?, ?, ?)";
        PreparedStatement pstmt = con.prepareStatement(query);

        // 첫 번째 레코드
        pstmt.setString(1, "Amit");
        pstmt.setInt(2, 3000);
pstmt.setString(3, "Hyderabad");
        pstmt.executeUpdate();

        // 두 번째 레코드
        pstmt.setString(1, "Kalyan");
        pstmt.setInt(2, 4000);
        pstmt.setString(3, "Vishakhapatnam");
        pstmt.executeUpdate();

        // 세 번째 레코드
        pstmt.setString(1, "Renuka");
        pstmt.setInt(2, 5000);
        pstmt.setString(3, "Delhi");
        pstmt.executeUpdate();

        // 네 번째 레코드
        pstmt.setString(1, "Archana");
        pstmt.setInt(2, 15000);
        pstmt.setString(3, "Mumbai");
        pstmt.executeUpdate();

        System.out.println("데이터 삽입 완료......");
    }
}

출력 결과

연결이 설정되었습니다......
데이터 삽입 완료......

데이터베이스를 확인해 보면 테이블에 다음과 같이 값이 삽입된 것을 확인할 수 있습니다.

+---------+--------+----------------+
| Name    | Salary | Location       |
+---------+--------+----------------+
| Amit    | 3000   | Hyderabad      |
| Kalyan  | 4000   | Vishakhapatnam |
| Renuka  | 5000   | Delhi          |
| Archana | 15000  | Mumbai         |
+---------+--------+----------------+
4 rows in set (0.00 sec)

이처럼 PreparedStatement를 활용하면 동일한 SQL 문을 재사용하면서 매번 다른 값을 안전하고 효율적으로 바인딩할 수 있습니다. 반복적인 데이터 삽입·수정 작업이 많은 애플리케이션에서는 반드시 익혀야 할 필수 도구입니다.