2012-12-22 25 views
5

Tôi đang lên kế hoạch viết một đánh chặn cho một EJB rằng sẽ làm cơ bản như sau:Làm cách nào để biết liệu giao dịch có hoạt động trong trình chặn đánh chặn Java EE 6 không?

@AroundInvoke 
public Object setContext(InvocationContext ctx) throws Exception { 
    em.createQuery("... set something [database specific] ...").getSingleResult(); 
    try { 
     return ctx.proceed(); 
    } finally { 
     em.flush(); 
     em.createQuery("... unset something [database specific] ...").getSingleResult(); 
    } 
} 

Vấn đề là em.flush() ném một ngoại lệ nếu nó được áp dụng cho một phương pháp chú thích với @TransactionAttribute (NOT_SUPPORTED) hoặc @TransactionAttribute (SUPPORTS) (nghĩa là các phương thức chỉ đọc), trong khi nó hoạt động tốt với các phương thức sử dụng mặc định @TransactionAttribute (YÊU CẦU) (tức là các phương thức thay đổi cơ sở dữ liệu).

Có cách nào để biết liệu giao dịch có đang hoạt động để tránh cuộc gọi đến em.flush() khi không có giao dịch nào đang chạy hay tôi phải tạo hai bộ chặn, một với em.flush () và một người không có nó?

Tôi không thể tiêm UserTransaction vì bean sử dụng giao dịch do container quản lý. Các phương thức giao dịch() của EntityManager chỉ làm việc với các giao dịch resource_local, không phải với các giao dịch JTA. Tôi cần em.flush() gọi để đảm bảo rằng truy vấn unset là điều cuối cùng chạy.

Là câu hỏi tiền thưởng, có ai biết nếu những gì tôi đang cố gắng làm là một loại thực hành không tốt? Tôi biết rằng thiết bị chặn chạy trong cùng một bối cảnh với bean, vì vậy sẽ an toàn để chia sẻ mọi thứ thông qua phiên cơ sở dữ liệu, nhưng tôi phải thực sự cẩn thận để bỏ đặt mọi thứ khi thoát vì kết nối được gộp trong vùng chứa.

Trả lời

9

Bạn có thể tiêm một TransactionSynchronizationRegistry và sử dụng getTransactionStatus để có được tình trạng của giao dịch trong bối cảnh hiện nay, nó sẽ trả về một int mà là một contant trong lớp Status, trong trường hợp của bạn, bạn đang tìm kiếm STATUS_NO_TRANSACTION

Tiêm :

@Resource 
TransactionSynchronizationRegistry tsr; 

Kiểm tra tình trạng giao dịch:

if (Status.STATUS_NO_TRANSACTION == tsr.getTransactionStatus()) { 
    // no transaction 
} 
+1

Cảm ơn, Tôi sẽ không bao giờ đoán được! Nó hoạt động tốt với một thay đổi nhỏ: ** @ Tài nguyên (tra cứu = "java: comp/TransactionSynchronizationRegistry") ** hoặc ** @ Tài nguyên (mappedName = "java: comp/TransactionSynchronizationRegistry") **. Không có tham số, @Resource sẽ xây dựng tên JNDI dựa trên tên lớp và tên biến của tôi. – marcus

+0

Tôi đoán rằng phụ thuộc vào máy chủ applicaiton bạn đang sử dụng –

+0

Vâng, tôi đang sử dụng JBoss AS 7.1. Tên JNDI có vẻ là di động, mặc dù, vì nó nằm trong JavaDoc. – marcus

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