2010-10-07 34 views
5

Tôi có một ứng dụng mà sử dụng mùa xuân 2,5 và Hibernate 3.Làm thế nào để thiết lập các giao dịch cho cả hai ứng dụng web và các công việc hàng loạt sử dụng Spring và Hibernate

Có một ứng dụng web với một lớp trình bày, một lớp servive và một DAO lớp, cũng như một số công việc Quartz chia sẻ cùng một dịch vụ và các lớp DAO.

Các giao dịch được khởi tạo trong các lớp khác nhau với các chú thích @Transactional, như thế này:

alt text

Nó dẫn tôi đến một vấn đề tôi đã mô tả ở đây: Controlling inner transaction settings from outer transaction with Spring 2.5

tôi đọc một chút thông tin về làm thế nào để thiết lập -up giao dịch với dây Spring và Hibernate cùng nhau. Có vẻ cách tiếp cận được khuyến nghị là khởi tạo các giao dịch trong tầng dịch vụ.

Điều tôi không thích là hầu hết các giao dịch chỉ tồn tại vì chúng được yêu cầu để ngủ đông hoạt động bình thường.

Và khi tôi thực sự cần một giao dịch cho một công việc gọi nhiều phương thức dịch vụ, có vẻ như tôi không có lựa chọn để tiếp tục khởi tạo giao dịch từ công việc. Vì vậy, di chuyển chú thích @Transactional từ DAO đến dịch vụ dường như không tạo ra bất kỳ sự khác biệt nào.

Bạn muốn giới thiệu các giao dịch thiết lập cho loại ứng dụng này như thế nào?

+0

xuất sắc câu hỏi và tôi đã định hỏi nó bản thân mình :) – willcodejavaforfood

+0

Giúp với một câu hỏi không phải là vui mừng khi giúp đỡ với một câu trả lời nhưng nó vẫn còn tốt để nghe; o) – Damien

Trả lời

5

Tôi đọc một chút về cách thiết lập giao dịch cho dây Spring và Hibernate cùng nhau. Có vẻ cách tiếp cận được khuyến nghị là khởi tạo các giao dịch trong tầng dịch vụ.

Chắc chắn. ranh giới giao dịch phải được thực hiện ở cấp lớp dịch vụ, chứ không phải ở cấp lớp DAO:

  • đơn vị làm việc là dịch vụ, không phải là DAO
  • bạn muốn có một giao dịch để span nhiều DAO nếu cần thiết.

Điều tôi không thích là hầu hết giao dịch chỉ tồn tại vì chúng được yêu cầu để ngủ đông hoạt động bình thường.

Bạn có thể giải thích phần này vì giao dịch không phải là Hibernate cụ thể.

Và khi tôi thực sự cần một giao dịch cho một công việc gọi nhiều phương thức dịch vụ, có vẻ như tôi không có lựa chọn để tiếp tục khởi tạo giao dịch từ công việc.

Nếu bạn muốn gọi nhiều dịch vụ bên trong một giao dịch bắt đầu từ lớp Job, kê khai dịch vụ của bạn như giao dịch với REQUIRED ngữ nghĩa (mặc định) và dựa vào tuyên truyền giao dịch mùa xuân (điều này áp dụng trừ khi bạn cần một cuộc gọi từ xa; trong trường hợp đó, hãy sử dụng các EJB).

Vì vậy, di chuyển chú thích @Transactional từ DAO sang dịch vụ dường như không tạo ra bất kỳ sự khác biệt nào.

không tạo sự khác biệt và thực tế mà bạn cần để bắt đầu giao dịch từ lớp Job khi chạy theo lô không làm những điều khác nhau.

Tôi nhiệt liệt khuyên bạn nên đọc Chapter 9. Transaction management.


(...) Vấn đề chính của tôi xuất phát từ Hibernate. Xin lỗi nếu tôi không rõ ràng.

Không sao cả. Chỉ là khi một câu hỏi là mơ hồ, bạn thường nhận được một câu trả lời mơ hồ :)

Từ tài liệu Hibernate: "các giao dịch cơ sở dữ liệu không bao giờ bắt buộc tất cả các thông tin liên lạc với một cơ sở dữ liệu có xảy ra bên trong một giao dịch..". Đó là lý do tại sao các nhà phát triển đưa các phương thức DAO giao dịch vào dự án của tôi.

Xin lỗi nhưng tuyên bố trên chỉ nói rằng "giao tiếp với một cơ sở dữ liệu có xảy ra bên một giao dịch", không có gì hơn, và quyết định để bắt đầu giao dịch nơi còn lại theo ý của bạn (thường là các dịch vụ lớp). Nếu bạn làm điều đó ở cấp DAO, điều gì sẽ xảy ra nếu MySuperService gọi DaoFooDaoBarDaoBar không thành công? Trong những trường hợp như vậy, có thể bạn sẽ muốn khôi phục tất cả các thay đổi, không chỉ những thay đổi được thực hiện trong DaoBar. Do đó cần phải kiểm soát giao dịch nơi đơn vị công việc bắt đầu.

IMHO, nhà phát triển cần một số hướng dẫn.

Điều đó có nghĩa là tất cả các dịch vụ của tôi phải được giao dịch? Ngay cả khi tôi chỉ đọc dữ liệu chẳng hạn?

Trước hết, tôi đề nghị để đọc Non-transactional data access and the auto-commit mode (em trai của Sessions and transactions) để làm rõ điều về "read-only giao dịch". Đọc toàn bộ trang là giá trị nó nhưng hãy để tôi chỉ trích dẫn một phần cụ thể này:

Nhiều nhà phát triển ứng dụng nghĩ rằng họ có thể nói chuyện với một cơ sở dữ liệu bên ngoài của một giao dịch . Điều này rõ ràng không phải là có thể; không có câu lệnh SQL nào có thể được gửi tới cơ sở dữ liệu bên ngoài cơ sở dữ liệu giao dịch. Thuật ngữ truy cập dữ liệu không hạn chế nghĩa là không có ranh giới giao dịch rõ ràng, không có giao dịch hệ thống và hành vi truy cập dữ liệu là chế độ tự động . Điều đó không có nghĩa là không có giao dịch cơ sở dữ liệu thực là .

Khi bạn đã hoàn tất với liên kết ở trên, lần đọc được đề xuất tiếp theo sẽ là @Transactional read-only flag pitfalls. Đây là phần có liên quan:

(...) Điểm mấu chốt là khi bạn sử dụng khung dựa trên ORM, cờ chỉ đọc là khá vô dụng và trong hầu hết các trường hợp bị bỏ qua. Nhưng nếu bạn vẫn khăng khăng sử dụng nó, luôn đặt chế độ công tác tuyên truyền để hỗ trợ, như thể hiện trong Liệt kê 9, vì vậy không có giao dịch được bắt đầu:

Liệt kê 9. Sử dụng chỉ đọc và SUPPORTS chế độ tuyên truyền cho chọn hoạt động

@Transactional(readOnly = true, propagation=Propagation.SUPPORTS) 
public TradeData getTrade(long tradeId) throws Exception { 
    return em.find(TradeData.class, tradeId); 
} 

Hơn thế nữa, chỉ cần tránh sử dụng các chú thích @Transactional hoàn toàn khi thực hiện các hoạt động đọc, như.210 trong Liệt kê 10:

Liệt kê 10. Loại bỏ các @Transactional chú thích cho chọn hoạt động

public TradeData getTrade(long tradeId) throws Exception { 
    return em.find(TradeData.class, tradeId); 
} 
+0

Cảm ơn lời giải thích của bạn Pascal. Tôi rõ ràng đã đọc Chương 9 nhưng vấn đề chính của tôi xuất phát từ Hibernate. Xin lỗi nếu tôi không rõ ràng. Từ tài liệu hibernate: "Các giao dịch cơ sở dữ liệu không bao giờ là tùy chọn. Tất cả các giao tiếp với một cơ sở dữ liệu phải xảy ra bên trong một giao dịch." Đó là lý do tại sao developpers đưa DAO phương thức giao dịch vào dự án của tôi. Điều đó có nghĩa là tất cả các dịch vụ của tôi phải được giao dịch? Ngay cả khi tôi chỉ đọc dữ liệu chẳng hạn? – Damien

+0

@Pascal Cảm ơn bạn đã dành thời gian và giải thích. – Damien

+0

@Damien Bạn được chào đón, vui vì bạn thấy nó hữu ích –

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