Câu trả lời:
Việc đẩy phiên làm việc buộc Hibernate phải đồng bộ hóa trạng thái trong bộ nhớ của Session
cơ sở dữ liệu (tức là ghi các thay đổi vào cơ sở dữ liệu). Theo mặc định, Hibernate sẽ tự động gửi các thay đổi cho bạn:
Cho phép xóa rõ ràng Session
quyền kiểm soát tốt hơn có thể được yêu cầu trong một số trường hợp (để nhận ID được chỉ định, để kiểm soát kích thước của Phiên, ...).
id = session.save(obj);
và giao dịch được cam kết ở dòng tiếp theo nhưng obj không được lưu cho DB, Tại sao? 2) Tôi đã lưu obj bằng cách sử dụng session.save(obj);
commit và trong khi quay lại, tôi đã sử dụng return obj.getprimaryID();
Trong trường hợp này, obj được lưu vào DB. Vậy tại sao lại có hành vi này?
Như đã nói đúng trong các câu trả lời ở trên, bằng cách gọi flush()
chúng ta buộc ngủ đông để thực thi các lệnh SQL trên Cơ sở dữ liệu. Nhưng hãy hiểu rằng những thay đổi chưa được "cam kết". Vì vậy, sau khi thực hiện xả và trước khi thực hiện cam kết, nếu bạn truy cập trực tiếp vào DB (ví dụ từ lời nhắc SQL) và kiểm tra các hàng đã sửa đổi, bạn sẽ KHÔNG thấy các thay đổi.
Điều này giống như việc mở 2 phiên lệnh SQL. Và những thay đổi được thực hiện trong 1 phiên sẽ không hiển thị với những người khác cho đến khi được cam kết.
Tôi chỉ biết rằng khi chúng tôi gọi session.flush()
các câu lệnh của chúng tôi được thực thi trong cơ sở dữ liệu nhưng không được cam kết.
Giả sử chúng ta không gọi flush()
phương thức trên đối tượng session và nếu chúng ta gọi phương thức commit thì nó sẽ thực hiện nội bộ các câu lệnh trên cơ sở dữ liệu và sau đó cam kết.
commit=flush+commit
(trong trường hợp chức năng)
Do đó, tôi kết luận rằng khi chúng ta gọi phương thức flush () trên đối tượng Session, thì nó không nhận được cam kết nhưng truy cập vào cơ sở dữ liệu và thực hiện truy vấn và cũng được khôi phục.
Để cam kết, chúng tôi sử dụng commit () trên đối tượng Giao dịch.
Việc đẩy phiên làm việc lấy dữ liệu hiện có trong phiên được đồng bộ hóa với dữ liệu trong cơ sở dữ liệu.
Thêm trên trang web Hibernate:
flush()
rất hữu ích, bởi vì hoàn toàn không có đảm bảo về thời điểm Phiên thực hiện các lệnh gọi JDBC, chỉ thứ tự mà chúng được thực thi - ngoại trừ bạn sử dụng flush()
.
Bạn có thể sử dụng flush
để buộc các ràng buộc xác thực phải được thực hiện và phát hiện ở một nơi đã biết hơn là khi giao dịch được cam kết. Có thể là như thếcommit
được gọi ngầm bởi một số logic khung, thông qua logic khai báo, vùng chứa hoặc bởi một khuôn mẫu. Trong trường hợp này, bất kỳ ngoại lệ nào được ném ra có thể khó bắt và xử lý (nó có thể quá cao trong mã).
Ví dụ: nếu bạn save()
là một đối tượng EmailAddress mới, có một ràng buộc duy nhất về địa chỉ, bạn sẽ không gặp lỗi cho đến khi bạn cam kết.
Việc gọi flush()
buộc hàng phải được chèn, ném Ngoại lệ nếu có bản sao.
Tuy nhiên, bạn sẽ phải quay lại phiên sau khi ngoại lệ.
Tôi chỉ muốn kết hợp tất cả các câu trả lời được đưa ra ở trên và cũng liên hệ phương thức Flush () với Session.save () để có tầm quan trọng hơn
Hibernate save () có thể được sử dụng để lưu thực thể vào cơ sở dữ liệu. Chúng tôi có thể gọi phương thức này bên ngoài một giao dịch, đó là lý do tại sao tôi không thích phương pháp này để lưu dữ liệu. Nếu chúng tôi sử dụng điều này mà không có giao dịch và chúng tôi có xếp tầng giữa các thực thể, thì chỉ thực thể chính được lưu trừ khi chúng tôi xóa phiên.
flush (): Buộc phiên hoạt động. Nó được sử dụng để đồng bộ hóa dữ liệu phiên với cơ sở dữ liệu.
Khi bạn gọi session.flush (), các câu lệnh được thực thi trong cơ sở dữ liệu nhưng nó sẽ không được cam kết. Nếu bạn không gọi session.flush () và nếu bạn gọi session.commit (), phương thức commit () bên trong thực thi câu lệnh và cam kết.
Vì vậy, commit () = flush + commit. Vì vậy, session.flush () chỉ thực hiện các câu lệnh trong cơ sở dữ liệu (nhưng không thực hiện các cam kết) và các câu lệnh KHÔNG TRONG BỘ NHỚ nữa. Nó chỉ buộc phiên hoạt động.
Vài điểm quan trọng:
Chúng ta nên tránh lưu bên ngoài ranh giới giao dịch, nếu không các thực thể được ánh xạ sẽ không được lưu gây ra sự không nhất quán dữ liệu. Việc quên xóa phiên là điều rất bình thường vì nó không đưa ra bất kỳ ngoại lệ hoặc cảnh báo nào. Theo mặc định, Hibernate sẽ tự động xóa các thay đổi cho bạn: trước khi thực hiện một số truy vấn khi giao dịch được cam kết Cho phép xóa rõ ràng Phiên cung cấp quyền kiểm soát tốt hơn có thể được yêu cầu trong một số trường hợp (để được gán ID, kiểm soát kích thước của Phiên )
Các flush()
phương pháp gây Hibernate để tuôn ra phiên. Bạn có thể cấu hình Hibernate để sử dụng chế độ xả cho phiên bằng setFlushMode()
phương pháp sử dụng . Để có được chế độ xả cho phiên hiện tại, bạn có thể sử dụng getFlushMode()
phương pháp. Để kiểm tra xem phiên có bị bẩn hay không, bạn có thể sử dụng isDirty()
phương pháp. Theo mặc định, Hibernate quản lý việc xả các phiên.
Như đã nêu trong tài liệu:
https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/cha Chapter/flushing/Flushing.html
Đỏ bừng
Flushing là quá trình đồng bộ hóa trạng thái của bối cảnh liên tục với cơ sở dữ liệu bên dưới. The
EntityManager
và HibernateSession
thể hiện một tập hợp các phương thức, qua đó nhà phát triển ứng dụng có thể thay đổi trạng thái liên tục của một thực thể.Bối cảnh liên tục hoạt động như một bộ nhớ cache ghi lại giao dịch, xếp hàng đợi bất kỳ thay đổi trạng thái thực thể nào. Giống như bất kỳ bộ nhớ đệm ghi sau nào, các thay đổi được áp dụng đầu tiên trong bộ nhớ và được đồng bộ hóa với cơ sở dữ liệu trong thời gian lưu. Các hoạt động tuôn ra tận dụng mọi thay đổi trạng thái thực thể và chuyển nó thành một
INSERT
,UPDATE
hoặcDELETE
tuyên bố.Chiến lược xả được đưa ra bởi flushMode của Phiên ngủ đông đang chạy hiện tại. Mặc dù JPA chỉ xác định hai chiến lược xả (
AUTO
vàCOMMIT
), nhưng Hibernate có một phổ rộng hơn nhiều loại xả:
ALWAYS
: Đổ phiên trước mỗi truy vấn;AUTO
: Đây là chế độ mặc định và nó chỉ xóa Phiên khi cần thiết;COMMIT
: Phiên cố gắng trì hoãn quá trình xả cho đến khi Giao dịch hiện tại được cam kết, mặc dù nó cũng có thể xả sớm;MANUAL
: Phiên xả ra được ủy quyền cho ứng dụng, ứng dụng này phải gọiSession.flush()
một cách rõ ràng để áp dụng các thay đổi ngữ cảnh liên tục.Theo mặc định, Hibernate sử dụng
AUTO
chế độ xả để kích hoạt chế độ xả trong các trường hợp sau:
- trước khi thực hiện một Giao dịch;
- trước khi thực hiện truy vấn JPQL / HQL chồng chéo với các hành động của thực thể được xếp hàng đợi;
- trước khi thực hiện bất kỳ truy vấn SQL gốc nào không có đồng bộ hóa đã đăng ký.
Gọi điện EntityManager#flush
không có tác dụng phụ . Nó được sử dụng thuận tiện cho các loại thực thể có giá trị ID được tạo (giá trị trình tự): một ID như vậy chỉ khả dụng khi đồng bộ hóa với lớp bền vững bên dưới. Nếu ID này là bắt buộc trước khi giao dịch hiện tại kết thúc (ví dụ: cho mục đích ghi nhật ký), thì việc xóa phiên là bắt buộc.