2011-09-01 24 views
9

Trong ứng dụng J2EE của chúng tôi, chúng tôi sử dụng một bean trạng thái EJB-3 để cho phép mã phía trước tạo, sửa đổi và lưu các thực thể liên tục (được quản lý thông qua JPA-2).Tại sao chúng ta phải tự xóa() EntityManager trong PersistenceContext mở rộng?

Nó trông giống như sau:

@LocalBean 
@Stateful 
@TransactionAttribute(TransactionAttributeType.NEVER) 
public class MyEntityController implements Serializable 
{ 
    @PersistenceContext(type = PersistenceContextType.EXTENDED) 
    private EntityManager em; 

    private MyEntity current; 

    public void create() 
    { 
     this.current = new MyEntity(); 
     em.persist(this.current); 
    } 

    public void load(Long id) 
    { 
     this.current = em.find(MyEntity.class, id); 
    } 

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW) 
    public void save() 
    { 
     em.flush(); 
    } 
} 

Rất quan trọng, để tránh quá sớm cam kết, chỉ có phương pháp save() nằm trong một giao dịch, vì vậy nếu chúng ta gọi là create(), chúng tôi chèn không có gì trong cơ sở dữ liệu.

Thật kỳ lạ, theo phương pháp save(), chúng tôi phải gọi em.flush() để thực sự nhấn cơ sở dữ liệu. Trong thực tế, tôi đã cố gắng và thấy rằng chúng tôi cũng có thể gọi em.isOpen() hoặc em.getFlushMode(), cũng bất cứ điều gì đó là "liên quan đến em".

Tôi không hiểu điểm này. Vì save() có trong giao dịch, tôi nghĩ rằng ở cuối phương thức, giao dịch sẽ được thực hiện và do đó trình quản lý thực thể liên tục sẽ tự động bị xóa. Tại sao tôi phải tự xóa nó?

Cảm ơn, Xavier

+0

Không cần phải 'tuôn ra() '. 'joinTransaction()' phải đủ để lưu các sửa đổi của bạn trong phương thức giao dịch của bạn. –

Trả lời

7

Để được trực tiếp và với kim loại, sẽ không có đối tượng đăng ký cho EntityManager trong câu hỏi cho đến khi bạn thực sự sử dụngtrong một giao dịch.

Chúng tôi trong miền ứng dụng-máy chủ sẽ tạo một trong các đối tượng này để thực hiện flush() và đăng ký với javax.transaction.TransactionSynchronizationRegistry hoặc javax.transaction.Transaction. Điều này không thể được thực hiện trừ khi có một giao dịch hoạt động.

Đó là dài và ngắn. Có, một máy chủ ứng dụng rất tốt có thể giữ một danh sách các tài nguyên mà nó cung cấp cho đậu trạng thái và tự động đăng ký chúng trong mọi giao dịch mà đậu trạng thái có thể bắt đầu hoặc tham gia. Nhược điểm của việc đó là bạn hoàn toàn mất khả năng quyết định những thứ đi vào giao dịch nào. Có thể bạn có 2 hoặc 3 giao dịch khác nhau để chạy trên các đơn vị bền vững khác nhau và đang tổng hợp công việc trong ngữ cảnh kiên trì mở rộng của bạn cho một giao dịch rất cụ thể. Nó thực sự là một vấn đề thiết kế và máy chủ ứng dụng nên để lại các quyết định như vậy cho chính ứng dụng đó.

Bạn sử dụng nó trong giao dịch và chúng tôi sẽ đăng ký giao dịch đó trong giao dịch. Đó là hợp đồng cơ bản.

Side lưu ý, tùy thuộc vào cách EntityManager cơ bản được xử lý, bất kỳ gọi dai dẳng đến EntityManager thể đủ để gây ra một tuôn ra hoàn chỉnh vào cuối của giao dịch. Chắc chắn, flush() là trực tiếp nhất và rõ ràng nhưng persist() hoặc thậm chí là find() có thể làm điều đó.

+1

Wooh, tôi mất một thời gian để hiểu rõ câu trả lời của bạn, nhưng bây giờ nó có ý nghĩa. Cảm ơn! –

+0

Trích dẫn có liên quan từ đặc tả JPA2.1 (7.6.4.1 Yêu cầu đối với Tuyên truyền bối cảnh liên tục) cho ngữ cảnh kiên trì không tuyên truyền: 'Nếu người quản lý thực thể được gọi trong giao dịch JTA, ngữ cảnh kiên trì sẽ được liên kết với giao dịch JTA '. –

0

Nếu bạn sử dụng bối cảnh kiên trì mở rộng tất cả các hoạt động trên các đơn vị quản lý thực hiện bên trong các phương pháp không giao dịch được xếp hàng đợi để được ghi vào cơ sở dữ liệu. Khi bạn gọi flush() trên trình quản lý thực thể trong một bối cảnh giao dịch, tất cả các thay đổi được xếp hàng đợi sẽ được ghi vào cơ sở dữ liệu. Nói cách khác, thực tế là bạn có một phương thức giao dịch không cam kết thay đổi chính nó khi thoát khỏi phương thức (như trong CMT), nhưng thực ra trình quản lý thực thể đang xả. Bạn có thể tìm thấy lời giải thích đầy đủ của quá trình này here

+2

Tôi thấy hướng dẫn này, nhưng có vẻ hơi khó hiểu. Nó nói "Điều này có nghĩa là bất kỳ phương pháp nào tồn tại, hợp nhất hoặc loại bỏ bạn gọi sẽ không thực sự dẫn đến việc thực thi JDBC và do đó cập nhật cơ sở dữ liệu cho đến khi bạn gọi EntityManager.flush theo cách thủ công." Điểm cho bạn :) Nhưng trong ví dụ thứ hai, nó nói rằng "không bao giờ() cập nhật sẽ được cam kết vào cuối phương thức checkout()", và thanh toán này() trống, không có bất kỳ sự tuôn ra nào. Làm thế nào bạn có thể giải thích ví dụ này? Ngoài ra, trong các mẫu JavaEE trong thế giới thực của Adam Bien, mẫu GateWay cũng có phương thức lưu trống: http://tinyurl.com/3o96xoh (trang 67). –

0

Vì không có cách nào để biết "khi nào" khách hàng được thực hiện với phiên (phạm vi mở rộng).

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