2012-03-03 21 views
9

Tôi bị SO nhầm lẫn bởi phiên và giao dịch. Về cơ bản tôi không thấy điểm có cả hai là gì, và tôi rất bối rối khi sử dụng cái này hay cái kia.Grails: Sự khác nhau giữa một phiên không bị xóa và một giao dịch được quay lại là gì?

Sự khác nhau giữa phiên không bị xóa và giao dịch không được cam kết là gì?

Tôi thậm chí không biết làm thế nào để hỏi những gì tôi không biết ... là có một nguồn cung cấp cho các ví dụ tốt về các tình huống giao dịch và phiên giao dịch phổ biến để tôi có thể thấy sự khác biệt?

Trả lời

18

Giao dịch trong Hibernate khá giống với giao dịch trong JDBC nói chung. Khi bạn nhận được số Connection từ số DataSource, giá trị mặc định là autocommit = true, vì vậy giao dịch được thay đổi thành autocommit = false. Cách đó thay đổi được thực hiện trong cơ sở dữ liệu chỉ khi cam kết rõ ràng thay vì mỗi khi bạn cập nhật.

Hibernate's Session thực hiện một số việc nhưng trong trường hợp này chức năng của nó là bộ nhớ cache cấp 1. Nó sử dụng một khái niệm được gọi là "writebehind giao dịch" cho hiệu suất để xếp hàng các thay đổi trong bộ nhớ cache đó và chỉ đẩy chúng vào cơ sở dữ liệu khi cần thiết. Vì vậy, ví dụ nếu bạn lấy một cá thể liên tục và thay đổi nó trong một luồng công việc đa phương thức phức tạp, trong đó mỗi phương thức có thể không thay đổi hoặc nhiều, chỉ cần một câu lệnh SQL cập nhật để Hibernate đợi cho đến khi cần thiết để tổng hợp chúng lại với nhau. Điều này là độc lập với việc bạn có đang chạy trong một giao dịch hay không - điều đó luôn xảy ra.

Nơi bộ nhớ cache phiên và giao dịch hoạt động kết hợp với nhau đang xả trong một giao dịch đang hoạt động. Kể từ khi Hibernate chờ đợi càng lâu càng tốt để tuôn ra thay đổi, nếu bạn không có trong một giao dịch và bạn tuôn ra, những thay đổi trở nên liên tục trong cơ sở dữ liệu ngay lập tức. Vì vậy, đó là một tối ưu hóa hiệu suất để giảm số lượng cơ sở dữ liệu viết. Nhưng nếu bạn đang trong một giao dịch và bạn tuôn ra phiên, bạn đẩy các thay đổi vào cơ sở dữ liệu. Nhưng cơ sở dữ liệu giữ các thay đổi trong hàng đợi giao dịch của nó. Vì vậy, mặc dù chúng nằm trong cơ sở dữ liệu, chúng không hiển thị với các kết nối khác cho đến khi bạn thực hiện giao dịch.

Lý tưởng là sẽ không có bất kỳ lệnh xóa nào rõ ràng và cam kết giao dịch sẽ kích hoạt trước khi cam kết và cả hai sẽ giảm thiểu số lần bạn cần truy cập vào cơ sở dữ liệu và giữ các thay đổi không được cam kết ẩn với người gọi khác. Nhưng bạn có thể tuôn ra nhiều lần tùy ý.

Một điều sẽ khiến Hibernate tự động xóa tự động thay mặt bạn là truy vấn. Như tôi đã nói, bạn có thể thực hiện nhiều thay đổi đối với các trường hợp liên tục (thậm chí xóa chúng) và chúng sẽ được xếp hàng đợi trong bộ nhớ cache phiên. Nhưng nếu bạn chạy một truy vấn (một công cụ tìm kiếm động, tiêu chí, HQL, vv) Hibernate không thể biết nếu những thay đổi xếp hàng sẽ ảnh hưởng đến truy vấn của bạn. Vì vậy, nó bi quan và tuôn ra để chắc chắn rằng mọi thứ đều phù hợp với truy vấn. Cơ sở dữ liệu sẽ sử dụng dữ liệu đã được xóa nhưng không được cam kết cho truy vấn của bạn và trả lại kết quả mong đợi. Đây là lý do chúng tôi khuyên bạn nên sử dụng phương thức withNewSession khi thực hiện truy vấn trong trình xác thực lớp miền tùy chỉnh, do đó bạn không bị xóa phiên hiện tại trong khi xác thực có thể gây ra hành vi lạ.

Các vấn đề liên quan