JDBC - Statements, PreparedStatement và CallableStatement
Sau khi có được kết nối, chúng tôi có thể tương tác với cơ sở dữ liệu. Các giao diện JDBC Statement, CallableStatement và PreparedStatement xác định các phương thức và thuộc tính cho phép bạn gửi các lệnh SQL hoặc PL / SQL và nhận dữ liệu từ cơ sở dữ liệu của bạn.
Chúng cũng xác định các phương pháp giúp kết nối sự khác biệt về kiểu dữ liệu giữa kiểu dữ liệu Java và SQL được sử dụng trong cơ sở dữ liệu.
Bảng sau đây cung cấp tóm tắt về mục đích của từng giao diện để quyết định giao diện sử dụng.
Giao diện | Sử dụng được khuyến cáo |
---|---|
Tuyên bố | Sử dụng nó để truy cập mục đích chung vào cơ sở dữ liệu của bạn. Hữu ích khi bạn đang sử dụng các câu lệnh SQL tĩnh trong thời gian chạy. Giao diện Statement không thể chấp nhận các tham số. |
Chuẩn bị sẵn sàng | Sử dụng điều này khi bạn định sử dụng các câu lệnh SQL nhiều lần. Giao diện PreparedStatement chấp nhận các tham số đầu vào trong thời gian chạy. |
CallableStatement | Sử dụng điều này khi bạn muốn truy cập các thủ tục được lưu trữ trong cơ sở dữ liệu. Giao diện CallableStatement cũng có thể chấp nhận các tham số đầu vào thời gian chạy. |
Đối tượng Tuyên bố
Tạo đối tượng câu lệnh
Trước khi bạn có thể sử dụng đối tượng Statement để thực thi một câu lệnh SQL, bạn cần tạo một đối tượng bằng phương thức createStatement () của đối tượng kết nối, như trong ví dụ sau:
Statement stmt = null;
try {
stmt = conn.createStatement( );
. . .
}
catch (SQLException e) {
. . .
}
finally {
. . .
}
Khi bạn đã tạo một đối tượng Statement, bạn có thể sử dụng nó để thực thi một câu lệnh SQL với một trong ba phương thức thực thi của nó.
boolean execute (String SQL): Trả về giá trị boolean true nếu một đối tượng ResultSet có thể được truy xuất; nếu không, nó trả về false. Sử dụng phương pháp này để thực thi các câu lệnh SQL DDL hoặc khi bạn cần sử dụng SQL động thực sự.
int executeUpdate (String SQL): Trả về số hàng bị ảnh hưởng bởi việc thực thi câu lệnh SQL. Sử dụng phương pháp này để thực thi các câu lệnh SQL mà bạn muốn nhận được một số hàng bị ảnh hưởng - ví dụ: câu lệnh INSERT, UPDATE hoặc DELETE.
ResultSet executeQuery (String SQL): Trả về một đối tượng ResultSet. Sử dụng phương pháp này khi bạn muốn nhận được một tập hợp kết quả, như bạn làm với câu lệnh SELECT.
Đối tượng Báo cáo Đóng
Cũng giống như bạn đóng một đối tượng Connection để tiết kiệm tài nguyên cơ sở dữ liệu, vì lý do tương tự, bạn cũng nên đóng đối tượng Statement.
Một cuộc gọi đơn giản đến phương thức close () sẽ thực hiện công việc. Nếu bạn đóng đối tượng Connection trước, nó cũng sẽ đóng đối tượng Statement. Tuy nhiên, bạn nên luôn đóng đối tượng Statement một cách rõ ràng để đảm bảo dọn dẹp đúng cách.
Statement stmt = null;
try {
stmt = conn.createStatement( );
. . .
}
catch (SQLException e) {
. . .
}
finally {
stmt.close();
}
Để hiểu rõ hơn, chúng tôi khuyên bạn nên nghiên cứu Hướng dẫn về Tuyên bố - Ví dụ .
Các đối tượng PreparedStatement
Các PreparedStatement giao diện mở rộng giao diện Statement, mang đến cho bạn thêm chức năng với một vài ưu điểm so với một đối tượng Statement generic.
Câu lệnh này cho phép bạn cung cấp các đối số một cách linh hoạt.
Tạo đối tượng PreparedStatement
PreparedStatement pstmt = null;
try {
String SQL = "Update Employees SET age = ? WHERE id = ?";
pstmt = conn.prepareStatement(SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
. . .
}
Tất cả các tham số trong JDBC được đại diện bởi ?ký hiệu, được gọi là dấu tham số. Bạn phải cung cấp giá trị cho mọi tham số trước khi thực hiện câu lệnh SQL.
Các setXXX() các phương thức liên kết giá trị với các tham số, trong đó XXXđại diện cho kiểu dữ liệu Java của giá trị bạn muốn liên kết với tham số đầu vào. Nếu bạn quên cung cấp các giá trị, bạn sẽ nhận được một SQLException.
Mỗi điểm đánh dấu tham số được gọi theo vị trí thứ tự của nó. Điểm đánh dấu đầu tiên đại diện cho vị trí 1, vị trí tiếp theo 2, v.v. Phương thức này khác với phương thức của chỉ số mảng Java, bắt đầu từ 0.
Tất cả Statement object'scác phương thức tương tác với cơ sở dữ liệu (a) execute (), (b) executeQuery (), và (c) executeUpdate () cũng hoạt động với đối tượng PreparedStatement. Tuy nhiên, các phương thức được sửa đổi để sử dụng các câu lệnh SQL có thể nhập các tham số.
Đóng đối tượng PreparedStatement
Cũng giống như bạn đóng đối tượng Statement, vì lý do tương tự, bạn cũng nên đóng đối tượng PreparedStatement.
Một cuộc gọi đơn giản đến phương thức close () sẽ thực hiện công việc. Nếu bạn đóng đối tượng Connection trước, nó cũng sẽ đóng đối tượng PreparedStatement. Tuy nhiên, bạn phải luôn đóng đối tượng PreparedStatement một cách rõ ràng để đảm bảo dọn dẹp đúng cách.
PreparedStatement pstmt = null;
try {
String SQL = "Update Employees SET age = ? WHERE id = ?";
pstmt = conn.prepareStatement(SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
pstmt.close();
}
Để hiểu rõ hơn, chúng ta cùng nghiên cứu Soạn thảo - Mã ví dụ .
Đối tượng CallableStatement
Cũng giống như một đối tượng Connection tạo ra các đối tượng Statement và PreparedStatement, nó cũng tạo ra đối tượng CallableStatement, đối tượng này sẽ được sử dụng để thực hiện một lệnh gọi đến một thủ tục được lưu trữ trong cơ sở dữ liệu.
Tạo đối tượng CallableStatement
Giả sử, bạn cần thực hiện thủ tục lưu trữ Oracle sau:
CREATE OR REPLACE PROCEDURE getEmpName
(EMP_ID IN NUMBER, EMP_FIRST OUT VARCHAR) AS
BEGIN
SELECT first INTO EMP_FIRST
FROM Employees
WHERE ID = EMP_ID;
END;
NOTE: Thủ tục được lưu trữ ở trên đã được viết cho Oracle, nhưng chúng tôi đang làm việc với cơ sở dữ liệu MySQL, vì vậy, chúng ta hãy viết cùng một quy trình được lưu trữ cho MySQL như sau để tạo nó trong cơ sở dữ liệu EMP -
DELIMITER $$
DROP PROCEDURE IF EXISTS `EMP`.`getEmpName` $$
CREATE PROCEDURE `EMP`.`getEmpName`
(IN EMP_ID INT, OUT EMP_FIRST VARCHAR(255))
BEGIN
SELECT first INTO EMP_FIRST
FROM Employees
WHERE ID = EMP_ID;
END $$
DELIMITER ;
Ba loại tham số tồn tại: IN, OUT và INOUT. Đối tượng PreparedStatement chỉ sử dụng tham số IN. Đối tượng CallableStatement có thể sử dụng cả ba.
Dưới đây là định nghĩa của mỗi -
Tham số | Sự miêu tả |
---|---|
TRONG | Một tham số có giá trị không xác định khi câu lệnh SQL được tạo. Bạn liên kết các giá trị với tham số IN bằng các phương thức setXXX (). |
NGOÀI | Một tham số có giá trị được cung cấp bởi câu lệnh SQL mà nó trả về. Bạn lấy giá trị từ các tham sốOUT bằng các phương thức getXXX (). |
GIỚI THIỆU | Một tham số cung cấp cả giá trị đầu vào và đầu ra. Bạn liên kết các biến với phương thức setXXX () và truy xuất giá trị bằng phương thức getXXX (). |
Đoạn mã sau đây cho thấy cách sử dụng Connection.prepareCall() phương pháp để khởi tạo một CallableStatement đối tượng dựa trên thủ tục được lưu trữ trước đó -
CallableStatement cstmt = null;
try {
String SQL = "{call getEmpName (?, ?)}";
cstmt = conn.prepareCall (SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
. . .
}
Biến chuỗi SQL, đại diện cho thủ tục được lưu trữ, với trình giữ chỗ tham số.
Sử dụng các đối tượng CallableStatement giống như sử dụng các đối tượng PreparedStatement. Bạn phải liên kết các giá trị với tất cả các tham số trước khi thực hiện câu lệnh, nếu không bạn sẽ nhận được một SQLException.
Nếu bạn có tham số IN, chỉ cần tuân theo các quy tắc và kỹ thuật tương tự áp dụng cho đối tượng PreparedStatement; sử dụng phương thức setXXX () tương ứng với kiểu dữ liệu Java mà bạn đang ràng buộc.
Khi bạn sử dụng các tham số OUT và INOUT, bạn phải sử dụng một phương thức CallableStatement bổ sung, registerOutParameter (). Phương thức registerOutParameter () liên kết kiểu dữ liệu JDBC với kiểu dữ liệu mà thủ tục được lưu trữ dự kiến sẽ trả về.
Khi bạn gọi thủ tục đã lưu trữ của mình, bạn lấy giá trị từ tham số OUT bằng phương thức getXXX () thích hợp. Phương thức này chuyển giá trị truy xuất của kiểu SQL sang kiểu dữ liệu Java.
Đóng đối tượng CallableStatement
Cũng giống như bạn đóng đối tượng Statement khác, vì lý do tương tự, bạn cũng nên đóng đối tượng CallableStatement.
Một cuộc gọi đơn giản đến phương thức close () sẽ thực hiện công việc. Nếu bạn đóng đối tượng Connection trước, nó cũng sẽ đóng đối tượng CallableStatement. Tuy nhiên, bạn phải luôn đóng đối tượng CallableStatement một cách rõ ràng để đảm bảo dọn dẹp đúng cách.
CallableStatement cstmt = null;
try {
String SQL = "{call getEmpName (?, ?)}";
cstmt = conn.prepareCall (SQL);
. . .
}
catch (SQLException e) {
. . .
}
finally {
cstmt.close();
}
Để hiểu rõ hơn, tôi khuyên bạn nên nghiên cứu Mã ví dụ - Callable .