← Назад к вопросам

В чем разница между видами Statement?

2.0 Middle🔥 121 комментариев
#Базы данных и SQL#Основы Java

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между Statement, PreparedStatement и CallableStatement

В JDBC есть три типа объектов для выполнения SQL запросов. Каждый решает свою задачу и имеет разные характеристики по производительности и безопасности.

Statement

Основной и самый простой способ выполнения SQL запросов. SQL отправляется сразу в БД в виде строки.

public class StatementExample {
    public static void main(String[] args) throws SQLException {
        Connection conn = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/mydb", "user", "password"
        );
        
        Statement stmt = conn.createStatement();
        
        String sql = "SELECT * FROM users WHERE age > 18";
        ResultSet rs = stmt.executeQuery(sql);
        
        while (rs.next()) {
            System.out.println(rs.getString("name"));
        }
        
        rs.close();
        stmt.close();
        conn.close();
    }
}

Характеристики Statement:

  • Простота: минимальный код
  • Уязвимость к SQL injection: опасно с пользовательскими данными
  • Низкая производительность: нет переиспользования при повторных запросах
  • Без параметров: SQL строка полностью готова

PreparedStatement

Предварительно компилируемый запрос с параметрами. БД парсит шаблон один раз, потом просто меняет параметры.

public class PreparedStatementExample {
    public static void main(String[] args) throws SQLException {
        Connection conn = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/mydb", "user", "password"
        );
        
        String sql = "SELECT * FROM users WHERE age > ? AND name = ?";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        
        pstmt.setInt(1, 18);
        pstmt.setString(2, "John");
        
        ResultSet rs = pstmt.executeQuery();
        while (rs.next()) {
            System.out.println(rs.getString("name"));
        }
        
        rs.close();
        pstmt.close();
        conn.close();
    }
}

Характеристики PreparedStatement:

  • Безопасность: защита от SQL injection через параметризацию
  • Производительность: план запроса компилируется один раз
  • Переиспользование: можно вызвать несколько раз с разными параметрами
  • Типизированные параметры: setInt(), setString() и т.д.
  • Batch операции: эффективная загрузка большого количества данных

Batch операции с PreparedStatement

public class BatchExample {
    public static void main(String[] args) throws SQLException {
        Connection conn = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/mydb", "user", "password"
        );
        
        String sql = "INSERT INTO users (name, age) VALUES (?, ?)";
        PreparedStatement pstmt = conn.prepareStatement(sql);
        
        for (int i = 0; i < 1000; i++) {
            pstmt.setString(1, "User" + i);
            pstmt.setInt(2, 20 + i % 50);
            pstmt.addBatch();
        }
        
        int[] results = pstmt.executeBatch();
        System.out.println("Вставлено записей: " + results.length);
        
        pstmt.close();
        conn.close();
    }
}

CallableStatement

Для вызова хранимых процедур в БД. Может возвращать несколько результатов и выходные параметры.

public class CallableStatementExample {
    public static void main(String[] args) throws SQLException {
        Connection conn = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/mydb", "user", "password"
        );
        
        String sql = "{call get_user_count(?, ?)}";        CallableStatement cstmt = conn.prepareCall(sql);
        
        cstmt.registerOutParameter(2, Types.INTEGER);
        cstmt.setInt(1, 18);
        
        cstmt.execute();
        
        int count = cstmt.getInt(2);
        System.out.println("Пользователей старше 18: " + count);
        
        cstmt.close();
        conn.close();
    }
}

Сравнительная таблица

СвойствоStatementPreparedStatementCallableStatement
ПростотаВысокаяСредняяНизкая
БезопасностьНизкаяВысокаяВысокая
ПроизводительностьНизкаяВысокаяЗависит от БД
ПереиспользованиеНетДаДа
Парсинг SQLКаждый разОдин разОдин раз
Хранимые процедурыНетНетДа

Защита от SQL injection

PreparedStatement автоматически экранирует значения параметров, предотвращая инъекции. Statement уязвим при конкатенации строк.

В современной разработке используют ORM-фреймворки (Hibernate, JPA), но понимание различий между Statement типами остаётся критично.