JDBC bài 6 Sử dụng đối tượng Statement để thực thi các câu truy vấn tĩnh
Sau khi mở kết nối thành công, ứng dụng Java cần một công cụ để "chuyên chở" các câu lệnh SQL gửi tới cơ sở dữ liệu. Trong JDBC, đối tượng Statement chính là phương tiện đảm nhận nhiệm vụ này. Nó được sử dụng chuyên biệt để thực thi các câu lệnh SQL tĩnh (Static SQL).
1. Khởi tạo đối tượng Statement
Đối tượng Statement không thể được tạo trực tiếp bằng từ khóa new. Bạn phải yêu cầu đối tượng Connection (đã mở thành công) tạo ra nó thông qua phương thức createStatement().
Luôn kết hợp với cơ chế Try-with-Resources (đã học ở Bài 5) để đảm bảo Statement được tự động đóng lại:
Java
try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
Statement stmt = conn.createStatement()) {
// Sử dụng stmt ở đây
}
2. Bộ ba phương thức thực thi cốt lõi
Tùy thuộc vào mục đích của câu lệnh SQL (đọc dữ liệu, ghi dữ liệu hay can thiệp cấu trúc), Statement cung cấp 3 phương thức thực thi khác nhau:
-
executeQuery(String sql): Dành riêng cho câu lệnhSELECT. Nó yêu cầu Database trả về dữ liệu và gói gọn kết quả đó vào một đối tượngResultSet. -
executeUpdate(String sql): Dành cho các câu lệnh thao tác dữ liệu DML (INSERT,UPDATE,DELETE). Nó trả về một số nguyên (int) đại diện cho số lượng dòng (records) bị ảnh hưởng trong Database. -
execute(String sql): Trả vềboolean(truenếu kết quả là ResultSet,falsenếu là số lượng dòng cập nhật hoặc không có gì). Phương thức này thường được dùng để chạy các lệnh định nghĩa cấu trúc DDL (CREATE TABLE,DROP TABLE,ALTER TABLE) hoặc khi bạn viết một công cụ chạy SQL động mà không biết trước người dùng nhập lệnh loại gì.
3. Thực hành: Tạo bảng và chèn dữ liệu bằng Statement
Dưới đây là đoạn mã thực tế sử dụng Statement để tạo một bảng users và thêm một người dùng mới vào database.
Java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class StatementExample {
private static final String URL = "jdbc:mysql://localhost:3306/shop_db";
private static final String USER = "root";
private static final String PASSWORD = "password123";
public static void main(String[] args) {
try (Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
Statement stmt = conn.createStatement()) {
// 1. Dùng execute() để tạo bảng (DDL)
String createTableSQL = "CREATE TABLE IF NOT EXISTS users ("
+ "id INT AUTO_INCREMENT PRIMARY KEY, "
+ "username VARCHAR(50) NOT NULL, "
+ "email VARCHAR(100) NOT NULL"
+ ")";
stmt.execute(createTableSQL);
System.out.println("Kiểm tra và tạo bảng thành công.");
// 2. Dùng executeUpdate() để chèn dữ liệu tĩnh (DML)
String insertSQL = "INSERT INTO users (username, email) VALUES ('nguyen_minh', 'minh@example.com')";
int affectedRows = stmt.executeUpdate(insertSQL);
System.out.println("Thêm thành công! Số dòng bị ảnh hưởng: " + affectedRows);
} catch (SQLException e) {
System.err.println("Lỗi SQLState: " + e.getSQLState());
e.printStackTrace();
}
}
}
4. Đặc điểm của "Truy vấn tĩnh" và những hạn chế chí mạng
"Truy vấn tĩnh" (Static SQL) nghĩa là toàn bộ câu lệnh SQL (bao gồm cả giá trị dữ liệu) được ghép lại thành một chuỗi (String) hoàn chỉnh duy nhất trước khi gửi xuống Database.
Nếu bạn muốn thêm dữ liệu do người dùng nhập từ giao diện vào, bạn bắt buộc phải dùng phép cộng chuỗi: String sql = "SELECT * FROM users WHERE username = '" + userInput + "'";
Cách làm này của Statement tồn tại hai nhược điểm cực kỳ lớn trong hệ thống thực tế:
-
Lỗ hổng bảo mật (SQL Injection): Kẻ gian có thể nhập các đoạn mã SQL độc hại vào biến
userInputđể đánh lừa hệ thống, dẫn đến việc xóa toàn bộ dữ liệu hoặc đánh cắp mật khẩu. -
Hiệu năng kém: Mỗi lần bạn gọi hàm thực thi, chuỗi SQL gửi xuống sẽ khác nhau (do giá trị cộng chuỗi khác nhau). Database bắt buộc phải phân tích cú pháp (parse) và biên dịch lại (compile) câu lệnh từ đầu, làm lãng phí tài nguyên hệ thống.
Vì những lý do trên, Statement thường chỉ được dùng để chạy các câu lệnh DDL (CREATE, DROP) hoặc các câu lệnh không hề có tham số đầu vào. Đối với các thao tác CRUD chứa dữ liệu người dùng, chúng ta sẽ sử dụng một phiên bản nâng cấp mạnh mẽ hơn (sẽ được tìm hiểu chuyên sâu ở Bài 11).
All rights reserved