이 글의 목적:

MySQL에 대한 스터디를 진행하다 보니 문득 우리가 사용하는 추상화된 기술들 안에서 PreparedStatement가 어떻게 동작하고 있을지 궁금해짐. 그래서 파헤쳐보기로 함

내용

Statement와 PreparedStatement

CREATE TABLE car(
    car_id BIGINT NOT NULL PRIMARY KEY,
    car_brand VARCHAR(20) NOT NULL,
    car_name VARCHAR(20) NOT NULL,
    car_type VARCHAR(10) NOT NULL
);

Statement

public class JdbcApplication {
    public static void main(String[] args) {
        String jdbcUrl = "jdbc:mysql://";
        String id = "";
        String password = "";

        Connection connection = null;
        Statement stmt = null;
        ResultSet rs = null;

        try {
            **connection = DriverManager.getConnection(jdbcUrl, id, password);
            // Statement 객체 획득
            stmt = connection.createStatement();
            // Statement 객체를 이용해 ResultSet 객체 획득
            rs = stmt.executeQuery("SELECT * FROM car WHERE car_id = 1");**

            while(rs.next()) {
                var car = createCar(rs);
                System.out.println(car);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                rs.close();
                stmt.close();
                connection.close();
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }

    private static Car createCar(ResultSet rs) throws SQLException {
        return new Car(rs.getLong(1), rs.getString(2), rs.getString(3), rs.getString(4));
    }

    private record Car(
            Long id,
            String brand,
            String name,
            String type
    ) { }
}

PreparedStatement

Connection connection = null;
// PreparedStatement 인터페이스로 변경
PreparedStatement stmt = null;
ResultSet rs = null;

try {
    **connection = DriverManager.getConnection(jdbcUrl + properties, id, password);
    // prepareStatement() 메서드 실행
    stmt = connection.prepareStatement("SELECT * FROM car WHERE car_id = ?");
    // 쿼리에 전달할 파라미터 세팅
    stmt.setLong(1, 1L);
    rs = stmt.executeQuery();**

    while(rs.next()) {
        var car = createCar(rs);
        System.out.println(car);
    }
}

비교

보통 파라미터 바인딩을 하지 않는 정적 쿼리를 사용하는 경우는 많지 않음

SQL Injection을 막기 위해 PreparedStatement를 권장함

JDBC는 이런 인터페이스들을 제공하지만 말 그대로 인터페이스만 제공하고 있기 때문에 이 인터페이스를 구현하는 구현체들에서 해당 스펙들을 구현해줘야 함 (MySQL은 제공함)

이런 스펙들은 JDBC 레이어에서 제공하는가?