4.1 Giới thiệu về giao dịch trong Hibernate

Đối với tất cả những điều trên, tôi muốn thêm thông tin về các giao dịch. Như bạn đã biết, giao dịch là một nhóm các hành động chỉ được thực hiện cùng nhau . Nếu bất kỳ hành động nào không thành công hoặc được thực hiện có lỗi, thì tất cả các hành động khác phải bị hủy.

Hibernate có thể hoạt động với hai loại giao dịch:

  • JDBC
  • JTA

Một giao dịch JDBC thực sự là một giao dịch cơ sở dữ liệu. Nó gắn với làm việc với cơ sở dữ liệu, với kết nối JDBC. Và anh ấy đảm bảo rằng các hành động khi làm việc với cơ sở dữ liệu được thực hiện như bình thường: tất cả hoặc không có gì.

JTA - Giao dịch là một giao dịch cấp ứng dụng. Nó không bị ràng buộc với bất kỳ cơ sở dữ liệu nào. Nhiệm vụ của nó là đảm bảo rằng một số hành động nhất định được thực hiện: tất cả hoặc không có gì.

Ví dụ: bạn có thể ghi dữ liệu vào một số cơ sở dữ liệu khác nhau trong một giao dịch JTA. Sau đó, nếu xảy ra lỗi, thì giao dịch JTA sẽ phải khôi phục các thay đổi trong tất cả các cơ sở dữ liệu. Ngay cả những thứ đã được thực thi thành công về cơ sở dữ liệu cụ thể.

4.2 Giao diện giao dịch ngủ đông

Trong thư viện Hibernate, một giao dịch được biểu thị bằng giao diện Giao dịch, giao diện này có thể có các cách triển khai khác nhau. Ví dụ, khi làm việc với Spring, Spring cung cấp cơ chế giao dịch JTA của riêng nó.

Các phương thức của giao diện này là:

# Phương pháp Sự miêu tả
1 bắt đầu() Bắt đầu một giao dịch mới
2 làm() Kết thúc giao dịch, đẩy/cam kết tất cả các thay đổi
3 khôi phục () Quay trở lại giao dịch hiện tại
4 setTimeout(int giây) Đặt thời gian thực hiện giao dịch tối đa
5 đang hoạt động() Kiểm tra xem một giao dịch có hoạt động hay không
6 wasRolledBack() Kiểm tra xem giao dịch có quay trở lại bình thường không
7 Đã cam kết() Kiểm tra nếu giao dịch đã được cam kết bình thường
số 8 đăng ký Đồng bộ hóa () Đăng ký gọi lại để kiểm soát giao dịch

Quan trọng! Tạo một đối tượng giao dịch và bắt đầu một giao dịch là hai việc khác nhau. Ở đây bạn có thể vẽ một sự tương tự với lớp Thread. Khi bạn tạo một đối tượng Thread(), JVM chưa bắt đầu một luồng mới. Để bắt đầu, bạn cần gọi phương thức start() trên đối tượng Thread. Tương tự với một giao dịch - nó cần gọi phương thức begin().

Một ví dụ về cách các giao dịch thường được xử lý trong Hibernate:


Session session = sessionFactory.openSession();
Transaction transaction = session.getTransaction();
try {
    transaction.begin();
    Long count = session.createQuery("select count(*) from Employee", Long.class).uniqueResult();
    transaction.commit();
}
catch (Exception e) {
	if (transaction.getStatus() == ACTIVE || transaction.getStatus() == MARKED_ROLLBACK) {
    transaction.rollback();
    }
}
finally {
	session.close();
	sessionFactory.close();
}

Chúng ta thấy ba điều ở đây:

Đầu tiên, tất cả công việc với cơ sở dữ liệu được bao bọc trong một giao dịch bằng cách gọi các phương thức begin()commit()Tất cả các hành động giữa các lần gọi đến hai phương thức này phải được thực hiện: tất cả cùng nhau hoặc không có gì.

Thứ hai, nếu có bất kỳ lỗi nào xảy ra, chúng tôi sẽ cố gắng khôi phục giao dịch - gọi phương thức rollback(). Điều này có nghĩa là TransactionManger trước tiên phải ghi lại tất cả các hành động giữa begin()commit(), sau đó trả lại mọi thứ như khi chúng ta gọi rollback().

Và nhân tiện, thực tế không phải là sẽ không có lỗi khi gọi phương thức quay lui. Sai lầm luôn xảy ra. Bạn chỉ cần chấp nhận sự thật này và sẵn sàng cho nó.

4.3 Quản lý giao dịch

Từ góc độ quản lý giao dịch, Hibernate chỉ là một trình bao bọc đối tượng nhẹ cho JDBC. Bản thân Hibernate không có các tính năng xử lý giao dịch. Giao dịch ngủ đông thực sự là một trình bao bọc cho giao dịch JDBC cơ bản (hoặc trình bao bọc giao dịch JTA). JDBCTransaction là mặc định. Ví dụ từ tệp cài đặt Hiberante:


hibernate.transaction.factory_class  org.hibernate.transaction.JTATransactionFactory
hibernate.transaction.factory_class  org.hibernate.transaction.JDBCTransactionFactory

Hãy xem lại mã của chúng tôi bằng cách sử dụng các giao dịch:


Session session = sessionFactory.openSession();
Transaction transaction = session.getTransaction();
transaction.begin();
//here is your code for working with the base
session.flush();
transaction.commit();
session.close();

Bây giờ hãy xem mã lớp JDBCTransaction:


public class JDBCTransaction implements Transaction {
 
    public void begin() throws HibernateException {
    	...
    	if (toggleAutoCommit) jdbcContext.connection().setAutoCommit(false);
    	...
    }
}

Đây là phương pháp để bắt đầu một giao dịch. Sau đó nhìn vào phương thức gửi:


public void commit() throws HibernateException {
    ...
    jdbcContext.connection().commit();
    ...
    jdbcContext.connection().setAutoCommit( true );
    ...
}

Bây giờ, hãy thay thế mã này thành mã ví dụ Hibernate:

ngủ đông Mã JDBC đơn giản

Session session = sessionFactory.openSession();
Transaction transaction = session.getTransaction();
transaction.begin();
//here is your code for working with the database
session.flush();
transaction.commit();
session.close();

Connection conn = jdbcContext.connection();
conn.setAutoCommit(false);
 
//here is your database code
conn.commit ()
conn.setAutoCommit(true);
conn.close();

Vì vậy, các giao dịch Hibernate gốc chỉ là các lệnh gọi JDBC gốc đến cơ sở dữ liệu. Không hơn không kém. Nhưng các giao dịch JTA thú vị hơn. Nhưng nhiều hơn về điều đó một thời gian khác.