4.1 Giao dịch và tính toàn vẹn của cơ sở dữ liệu

Chế độ hoạt động bình thường của cơ sở dữ liệu là khi nó nhận được hàng nghìn yêu cầu mỗi phút từ hàng trăm máy khách khác nhau. Trong trường hợp này, các tình huống thường phát sinh khi cùng một dữ liệu được truy cập từ các truy vấn khác nhau.

Tuy nhiên, ít thường xuyên hơn, đôi khi có những tình huống khi một yêu cầu đọc một dòng nhất định và một yêu cầu khác thay đổi nó cùng một lúc. Hãy tưởng tượng điều gì sẽ xảy ra nếu ai đó đọc một dòng chỉ bị thay đổi một nửa? Chẳng có gì tốt đẹp cả.

Vấn đề này được giải quyết theo nhiều cách. Đầu tiên, bạn chỉ có thể khóa dòng thay đổi. Cả hai để đọc và viết. Phương pháp này hoạt động, nhưng tốc độ của cơ sở bị ảnh hưởng rất nhiều.

Cách thứ hai là khóa chuỗi chỉ để viết. Tuy nhiên, sẽ vẫn có vấn đề khi ai đó cố đọc dòng đã sửa đổi một phần. Kết luận - không nên xảy ra tình trạng dòng bị thay đổi một phần.

Do đó, họ đã nghĩ ra phương pháp thứ ba - giao dịch. Giao dịch là một nhóm các hành động được thực hiện cùng nhau hoặc không thực hiện gì cả. Không thể có tình huống trong đó một phần của hành động được thực hiện và phần thứ hai thì không. Nếu không thể thực hiện tất cả các thay đổi thì tất cả các thay đổi đã thực hiện sẽ được khôi phục.

Bất kỳ máy chủ SQL hiện đại nào cũng chỉ cho phép bạn thay đổi dữ liệu trong các giao dịch. Bạn mở một giao dịch, thực hiện bất kỳ thay đổi nào đối với bất kỳ số lượng bảng nào và cam kết giao dịch. Sau đó, SQL Server sẽ cố gắng thực hiện các thay đổi. Nếu mọi thứ đều ổn, thì chúng sẽ được thêm vào cơ sở dữ liệu chung. Nếu có vấn đề, thì tất cả các thay đổi sẽ bị hủy.

Hibernate cũng sử dụng mô hình này. Đó là lý do tại sao trong bài giảng trước, chúng ta đã thấy rằng khi cố gắng lưu đối tượng Nhân viên vào cơ sở dữ liệu, một giao dịch được mở đầu tiên và sau khi lưu, nó được cam kết.

Chúng ta sẽ đi vào chủ đề này chi tiết hơn, nhưng bây giờ, chỉ cần biết tại sao các giao dịch lại cần thiết và chúng thường được sử dụng ở đâu.

4.2 Lấy đối tượng

Nếu Hibernate thực hiện yêu cầu lấy dữ liệu, thì không cần mở giao dịch một cách rõ ràng. Bản thân Hibernate sẽ làm điều này nếu nó thấy phù hợp: nó có các cài đặt của nó, cũng như các cài đặt của máy chủ SQL.

Chúng tôi sẽ phân tích cách làm việc với cơ sở dữ liệu. Và cách đơn giản nhất là lấy một đối tượng bằng ID của nó . Để làm điều này, hãy sử dụng phương thức get()trên đối tượng phiên . Hình thức chung của một yêu cầu như vậy:

Class Name = session.get(Class.class, ID);

Ví dụ:

public User getUserById(Integer id) {
    try (Session session = sessionFactory.openSession()) {
        User user = session.get(User.class, id);
        return user;
    }
}

4.3 Lưu (thêm) đối tượng

Nếu bạn muốn lưu đối tượng của mình vào cơ sở dữ liệu, thì một truy vấn sẽ được thực hiện ở cấp độ SQLCHÈN. Do đó, hành động của bạn phải được thực hiện như một giao dịch riêng biệt. Ngoài ra, tốt hơn là sử dụng phương thức persist()của đối tượng phiên cho sự kiên trì .

Hình thức chung của một yêu cầu như vậy:

session.persist(An object);

Phương thức persist()thay đổi không chỉ cơ sở, mà cả đối tượng. Có điều là khi ta thêm một đối tượng vào cơ sở dữ liệu thì đối tượng này chưa có ID riêng trước khi thêm vào . Vâng, thường là như vậy, mặc dù có những sắc thái. Và sau khi thêm đối tượng đã có ID .

public boolean saveUser(User user) {
    try (Session session = sessionFactory.openSession()) {
            Transaction transaction = session.beginTransaction();
            session.persist(user);
            transaction.commit();
            return true;
    }
    catch() {
    return false;
   	}
}

Đối tượng Session cũng có một phương thức save()thực hiện chức năng tương tự. Chỉ là phương thức này save()là tiêu chuẩn Hibernate cũ và phương thức này persist()là tiêu chuẩn JPA.

4.4 Xóa đối tượng

Nếu bạn muốn xóa một đối tượng hiện có, thì việc này rất dễ thực hiện. Để làm điều này, đối tượng phiên có một phương thức đặc biệt - remove().

Hình thức chung của một yêu cầu như vậy:

session.remove(An object);

Và, tất nhiên, hãy viết mã với một ví dụ:

public boolean removeUser(User user) {
    try (Session session = sessionFactory.openSession()) {
            Transaction transaction = session.beginTransaction();
            session.remove(user);
            transaction.commit();
            return true;
    }
    catch() {
    return false;
   	}
}

Tại sao nó lại khó khăn như vậy, bạn hỏi?

Chà, trước hết, bất kỳ thay đổi nào đối với cơ sở dữ liệu luôn có những hậu quả khác nhau và không phải lúc nào cũng rõ ràng. Và thứ hai, đối tượng này có thể có các đối tượng con được liên kết với nó, v.v. Vì vậy, các kịch bản xóa thường không tầm thường.