Hướng dẫn Java JDBC: Transaction là gì? Code ví dụ transaction với JDBC
Chắc hẳn bạn đã nghe nhiều tới transaction trong lập trình, hệ điều hành… vậy transaction là gì?
1. Transaction là gì?
Transaction là 1 giao dịch (hay còn gọi là 1 giao tác) bao gồm 1 loạt các hành động được phải được thực hiện thành công cùng nhau, nếu 1 hành động thất bại thì tất cả các hành động trong loạt hành động đó sẽ trở về trạng thái ban đầu.
Ví dụ bạn có 2 tài khoản ngân hàng A và B, bạn chuyển 1.000.000đ từ tài khoản A vào tài khoản B.
Transaction ở đây sẽ gồm 2 hành động:
- Tài khoản A bị trừ 1.000.000đ
- Tài khoản B cộng thêm 1.000.000đ
Bây giờ A bị trừ 1.000.000đ nhưng vì 1 lý do nào đấy B bị lỗi không nhận được 1.000.000đ thì transaction sẽ bị hủy, số tiền của 2 tài khoản A và B sẽ không bị thay đổi.
Chính vì ràng buộc phải hoàn thành cùng nhau nên transaction được áp dụng nhiều trong các hành động yêu cầu độ tin cậy, đảm bảo tính chính xác dữ liệu…
Hướng dẫn Java JDBC: Transaction là gì? Code ví dụ transaction với JDBC
Nhược điểm của transaction
Đôi khi một số trường hợp do phần cứng, mạng internet mà transaction hoạt động không đúng và người ta phải ghi log lại để khắc phục điều đó.
Ví dụ:
Bạn ra cây ATM rút tiền, bạn gửi lệnh rút 1.000.000đ, tài khoản trong ngân hàng bị trừ 1.000.000đ nhưng sau đấy mất mạng –> không thể xác định được cây ATM đã trả tiền ra chưa, nên số tiền 1.000.000đ sẽ không được hoàn lại tài khoản.
Nếu bạn chưa nhận được 1.000.000đ thì sẽ cần thông báo với ngân hàng, họ sẽ kiểm tra log trên server và log trên cây ATM để xác nhận và hoàn trả lại tiền cho bạn.
2. Ví dụ Transaction với JDBC
JDBC chịu trách nhiệm giao tiếp với database do đó nó sẽ thực hiện tạo transaction khi truy vấn dữ liệu tới database.
Mình sẽ thực hiện code ví dụ trường hợp chuyển tiền giữa 2 tài khoản ngân hàng.
Giả sử số tiền trong mỗi tài khoản chỉ được chứa số tiền nhỏ hon 100.000.000đ, nếu 1 tài khoản được cập nhật số tiền >= 100.000.000đ thì sẽ xảy ra lỗi.
Tài khoản A và tài khoản B đều có 90.000.000đ, bây giờ ta thực hiện chuyển 50.000.000đ từ A sang B trong trường hợp có và không dùng transaction để xem kết quả:
Ở ví dụ này mình sử dụng:
- MySQL làm cơ sở dữ liệu (Xem lại: Cài đặt và cấu hình MySQL)
- Eclipse
- Maven
Tạo cơ sở dữ liệu: “demo-jdbc-transaction”
CREATE SCHEMA `demo-jdbc-transaction` ;
Tạo table “account_banking”
CREATE TABLE `demo-jdbc-transaction`.`account_banking` ( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NULL, `amount` DECIMAL(13,5) NULL, PRIMARY KEY (`id`), UNIQUE INDEX `name_UNIQUE` (`name` ASC));
- cột amount mình để là DECIMAL(13,5) tức là số thực có 5 chữ số sau dấu phẩy và chữ 8 số trước dấu phẩy, nếu update amount >= 100.000.000,0 tức là lớn hơn 8 chữ số trước dấu phẩy nên sẽ xảy ra lỗi.
- cột name mình để là unique tức là không trùng nhau, nếu trung sẽ xảy ra lỗi.
Tạo 2 bản ghi cho tài khoản A và B:
INSERT INTO `demo-jdbc-transaction`.`account_banking` (`name`, `amount`) VALUES ('A', 90000000.0); INSERT INTO `demo-jdbc-transaction`.`account_banking` (`name`, `amount`) VALUES ('B', 90000000.0);
Code ví dụ:
Hướng dẫn Java JDBC: Transaction là gì? Code ví dụ transaction với JDBC
Thực hiện chuyển 50.000.000đ từ A sang B mà có sử dụng transaction:
A bị trừ 50.000.000đ còn B được cộng thêm 50.000.000đ nên sẽ update amount của A thành 40.000.000đ còn B là 140.000.000đ
package stackjava.com.demojdbc.statement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class UpdateWithTransaction { public static void main(String[] args) throws SQLException, ClassNotFoundException { Class.forName("com.mysql.jdbc.Driver"); Connection dbConnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo-jdbc-transaction", "root", "admin1234"); Statement stmt = dbConnection.createStatement(); dbConnection.setAutoCommit(false); try { stmt.executeUpdate("UPDATE account_banking SET amount = 40000000.0 WHERE name = 'A'"); stmt.executeUpdate("UPDATE account_banking SET amount = 140000000.0 WHERE name = 'B'"); dbConnection.commit(); } catch (Exception e) { e.printStackTrace(); dbConnection.rollback(); } dbConnection.close(); } }
Giải thích:
- dbConnection.setAutoCommit(false): dữ liệu sẽ chỉ update vào database khi gọi lệnh commit()
- dbConnection.rollback(): lấy lại dữ liệu ban đầu.
Kết quả:
Câu lệnh update thứ nhất thành công nhưng câu lệnh update thứ 2 xảy ra lỗi lên dữ liệu sẽ không bị thay đổi
Thực hiện chuyển 50.000.000đ từ A sang B mà không sử dụng transaction:
package stackjava.com.demojdbc.statement; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class UpdateWithoutTransaction { public static void main(String[] args) throws SQLException, ClassNotFoundException { Class.forName("com.mysql.jdbc.Driver"); Connection dbConnection = DriverManager.getConnection("jdbc:mysql://localhost:3306/demo-jdbc-transaction", "root", "admin1234"); Statement stmt = dbConnection.createStatement(); stmt.executeUpdate("UPDATE account_banking SET amount = 40000000.0 WHERE name = 'A'"); stmt.executeUpdate("UPDATE account_banking SET amount = 140000000.0 WHERE name = 'B'"); dbConnection.close(); } }
Kết quả:
Sau khi câu lệnh thứ nhất thành công nó sẽ update dữ liệu vào database luôn
Câu lệnh thứ hai xảy ra lỗi nhưng không phục hồi lại dữ liệu đã thay đổi trước đó.
Trên đây là ví dụ đơn giản nhất về transaction, các bạn có thể thử với trường hợp khác.
Ví dụ cột name mình đang để là unique –> các bạn sử dụng transaction, thực hiện câu lệnh insert mới account với name là C, D, A nó sẽ xảy ra lỗi và không insert gì cả vì A đã tồn tại sẵn trong database.
Hướng dẫn Java JDBC: Transaction là gì? Code ví dụ transaction với JDBC
Okay, Done!
Download code ví dụ trên tại đây
References: https://docs.oracle.com/javase/tutorial/jdbc/basics/transactions.html