2012-12-31 27 views
9

Tôi đã bắt đầu sử dụng các giao dịch cấp phương tiện Guice như được mô tả here. Tôi có một thông báo nhưGuice @Transactional không bắt đầu giao dịch

@Inject 
private EntityManager entityManager; 

@Transactional 
public UserSession createSession(User user, String browser) { 
    UserSession session = new UserSession(user, browser); 
    entityManager.persist(session); 
} 

Từ mô tả ngắn tôi nghĩ là đủ. Nhưng tôi nhận được một lỗi gây ra không có giao dịch được bắt đầu. Nó chỉ hoạt động nếu tôi bắt đầu và cam kết nó một mình.

Đối tượng được tạo bởi Guice khi bắt đầu ứng dụng của tôi trong trình khởi tạo. cùng một Instance được sử dụng cho mỗi yêu cầu.

Tại sao nó không hoạt động? Các chú thích phương thức

Trả lời

6

@Transactional chú thích phương thức hoạt động qua AOP, trong đó Guice đáp ứng yêu cầu Foo bằng cách tạo đối tượng proxy chặn các cuộc gọi phương thức được chú thích đó và (tùy chọn) chuyển tiếp chúng đến đối tượng thực. Hãy chắc chắn rằng sau là đúng:

  1. Bạn đã tạo đối tượng với phương pháp @Transactional qua Guice, vì Guice khác sẽ không có bất kỳ cơ hội để cung cấp proxy để thay thế.

  2. Cả lớp học lẫn phương pháp đều không được đánh dấu final, vì AOP không thể ghi đè dễ dàng các lớp đó.

  3. Bạn đã cài đặt JpaPersistModule hoặc một số hình thức khác là PersistModule. Lưu ý từ mã nguồn đó mô-đun này thực sự là những gì liên kết các MethodInterceptor với chú thích @Transactional.

Nếu điều này không phù hợp với nhu cầu của bạn, hãy nhớ rằng bạn luôn có thể đi theo số AOP documentation để viết trình chặn đánh chặn phương pháp của riêng bạn. Chúc may mắn!

+0

"Không có đối tượng và phương pháp nào được đánh dấu cuối cùng" Không nên là "Không phải lớp * cũng không phải là phương pháp được đánh dấu cuối cùng"? –

+0

Yup, trượt của tâm trí. Đã sửa. –

2

Sau khi kiểm tra lại mọi thứ, nó không hoạt động. Phần buồn cười là nó làm việc ở giữa, nhưng chỉ mỗi trăm lần.

Sau một số thử nghiệm bổ sung, tôi thấy rằng tôi cần tạo lại các Lớp trên mỗi Yêu cầu. Trước khi tôi chỉ tạo ra chúng khi bắt đầu ứng dụng. Bây giờ nó có vẻ hoạt động hoàn hảo.

Cảm ơn các mẹo đã giúp tôi điều tra thêm.

0

Tôi có vấn đề này trong tình huống sau đây, vì vậy tôi nghĩ rằng tôi muốn gửi giải pháp của tôi ở đây, quá:

BusinessLogic yêu cầu hai đối số nhà xây dựng: MyDao, mà tôi về mặt lý thuyết có thể nhận được từ Guice, và một số đối tượng khác mà tôi có thể không phải nhận được từ guice.
Vì vậy, tôi đã tạo một BusinessLogicProvider (extends AbstactProvider), nhưng nó không được sử dụng với bind(BusinessLogic.class).toProvider(BusinessLogicProvider)). Bây giờ tôi chỉ ràng buộc BusinessLogicProvider như bất kỳ loại Guice được phục vụ: bind(BusinessLogicProvider.class);

Bên trong lớp BusinessLogicProvider của tôi bây giờ tôi có thể sử dụng @Inject trên private Provider<MyDao> daoProvider;

Sau đó, trong public BusinessLogic get() phương pháp 's BusinessLogicProvider, tôi có thể gọi tới BusinessLogic 's constructor với hai đối số cần thiết: daoProvider.get() và đối tượng khác tôi không thể nhận được từ guice.

Các Pitfall: khi @Inject ed private Provider<MyDao> daoProvider; của BusinessLogicProvider của tôi không phải là loại Provider<MyDao> (nhưng simpy loại MyDao), nó sẽ không làm việc.
Ngay cả khi @Inject ed MyDaosẽ có nguồn gốc từ guice, guice cần tạo một cái mới mỗi khi bạn tạo nhanh BusinessLogic.

1

Tôi gặp sự cố tương tự như sự cố của bạn và nó đã được giải quyết bằng cách chuyển từ @ javax.transaction.Transactional sang @ com.google.inject.persist.Transactional. Rõ ràng Guice-Persist không hỗ trợ chú thích @Transactional từ API giao dịch Java.

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