Có nên đóng cửa JPA Entity Manager không?


82

Tôi có phương pháp dưới đây.

public Profile readUser(String email){
    EntityManager em = EMF.get().createEntityManager();
    return em.find(Profile.class, email);
}

Việc sử dụng trình quản lý thực thể ở trên có ổn không? Hoặc Nó là cần thiết để đóng em? Bất kỳ đề xuất xin vui lòng.



Không, nhất quyết không. Trừ khi bạn muốn rò rỉ ...

Câu trả lời:


131

Tôi cho rằng câu trả lời là: nó phụ thuộc .

Người quản lý thực thể của bạn là chìa khóa để có quyền truy cập vào ngữ cảnh nơi các thực thể cư trú. Nếu ứng dụng của bạn là ứng dụng JSE, bạn phải xem xét tuổi thọ của ngữ cảnh của bạn là bao nhiêu.

Hãy xem xét rằng bạn sẽ tạo một trình quản lý thực thể theo yêu cầu của người dùng. Vì vậy, trong khi bạn đang thực hiện một yêu cầu nhất định, bạn sẽ giữ cho trình quản lý thực thể của mình mở và khi bạn hoàn thành yêu cầu đó, bạn sẽ đóng nó.

Trong ứng dụng JSE, bạn có thể đã cân nhắc rằng bạn muốn giữ trình quản lý thực thể của mình mở toàn bộ vòng đời của ứng dụng (giả sử bạn không xử lý lượng lớn dữ liệu) sau đó bạn đóng nó khi ứng dụng của bạn tắt.

Điểm mấu chốt, khi bạn mở và khi nào bạn đóng hoàn toàn phụ thuộc vào chiến lược và thiết kế của bạn. Bạn đóng nó khi bạn không còn cần các thực thể trong ngữ cảnh của nó nữa.

Trong ví dụ của bạn, điều đó không rõ ràng, nhưng vì bạn đang tạo EM trong phương thức, bạn nên đóng nó trước khi quay lại, nếu không, bạn sẽ không còn quyền truy cập vào nó nữa (trừ khi bạn đang giữ nó trong một số đăng ký, mà không được hiển thị trong mã).

Nếu bạn không đóng nó, các thực thể của bạn sẽ được giữ nguyên như đính kèm, ngay cả sau khi bạn sử dụng xong chúng. Ngữ cảnh của bạn sẽ được giữ nguyên ngay cả khi bạn không thể truy cập EM của mình nữa.

Các JPA Specification chứa thêm chi tiết. Trong phần 7.7 Biểu đồ tồn tại do ứng dụng quản lý có nội dung:

Khi sử dụng trình quản lý thực thể do ứng dụng quản lý, ứng dụng sẽ tương tác trực tiếp với nhà máy quản lý thực thể của nhà cung cấp độ bền để quản lý vòng đời của trình quản lý thực thể và thu thập và hủy bỏ các ngữ cảnh tồn tại.

Tất cả các bối cảnh liên tục do ứng dụng quản lý như vậy đều được mở rộng phạm vi và có thể kéo dài nhiều giao dịch.

Các EntityManagerFactory.createEntityManagerphương pháp và EntityManager closeisOpenphương pháp được sử dụng để quản lý vòng đời của một người quản lý thực thể ứng dụng quản lý và bối cảnh bền bỉ liên quan.

Bối cảnh liên tục mở rộng tồn tại từ thời điểm mà người quản lý thực thể đã được tạo bằng cách sử dụng EntityManagerFactory.createEntityManagercho đến khi người quản lý thực thể bị đóng bằng phương tiện EntityManager.close.

Bối cảnh tồn tại mở rộng thu được từ trình quản lý thực thể do ứng dụng quản lý là một ngữ cảnh tồn tại độc lập mà nó không được truyền với giao dịch.

[...] EntityManager.closePhương thức đóng một trình quản lý thực thể để giải phóng ngữ cảnh tồn tại của nó và các tài nguyên khác. Sau khi gọi close, ứng dụng không được gọi thêm bất kỳ phương thức nào trên EntityManagerphiên bản ngoại trừ getTransactionisOpen, hoặc IllegalStateExceptionsẽ được ném. Nếu phương thức đóng được gọi khi một giao dịch đang hoạt động, ngữ cảnh liên tục vẫn được quản lý cho đến khi giao dịch hoàn tất.

Các EntityManager.isOpenphương pháp cho biết người quản lý đơn vị đang mở. Các isOpenphương thức trả về đúng cho đến khi người quản lý thực thể đã bị đóng cửa. Để thực sự hiểu cách hoạt động của điều này, điều quan trọng là phải hiểu mối quan hệ giữa người quản lý thực thể và bối cảnh.

Vì vậy, như bạn có thể thấy trình quản lý thực thể là giao diện công khai mà qua đó bạn truy cập vào các thực thể của mình, tuy nhiên, các thực thể của bạn nằm trong một ngữ cảnh, được gắn với trình quản lý thực thể của bạn. Hiểu được vòng đời của các loại bối cảnh khác nhau sẽ trả lời câu hỏi của bạn.

Các bối cảnh liên tục có thể thuộc nhiều loại khác nhau. Trong các ứng dụng Java EE, bạn có thể có ngữ cảnh duy trì phạm vi giao dịch hoặc ngữ cảnh tồn tại kéo dài . Trong ứng dụng JSE, bản chất của ngữ cảnh được kiểm soát bởi nhà phát triển .

Khi bạn yêu cầu một thực thể cho người quản lý thực thể của mình, nó sẽ tìm kiếm thực thể trong ngữ cảnh đính kèm của nó, nếu nó tìm thấy thực thể ở đó, thì nó sẽ trả về nó, nếu không, nó lấy thực thể đó từ cơ sở dữ liệu. Các lệnh gọi tiếp theo cho thực thể này trong ngữ cảnh sẽ trả về cùng một thực thể.

Phạm vi giao dịch

Trong ứng dụng Java EE sử dụng ngữ cảnh duy trì phạm vi giao dịch, khi bạn truy cập trình quản lý thực thể lần đầu tiên, nó sẽ kiểm tra xem giao dịch JTA hiện tại có ngữ cảnh đính kèm hay không nếu chưa có ngữ cảnh nào, ngữ cảnh mới được tạo và trình quản lý thực thể được liên kết với bối cảnh này. Sau đó, thực thể được đọc từ cơ sở dữ liệu (o từ bộ đệm nếu có) và nó được đặt vào ngữ cảnh. Khi giao dịch của bạn kết thúc (cam kết hoặc khôi phục), ngữ cảnh sẽ trở nên không hợp lệ và bất kỳ thực thể nào trong đó trở nên tách rời. Đây là kịch bản cổ điển cho các phiên không trạng thái.

@PersistenceContext(unitName="EmplService")
EntityManager em;

Điều này cũng có nghĩa là tùy thuộc vào cách bạn thiết kế các giao dịch của mình, bạn có thể kết thúc với nhiều hơn một ngữ cảnh.

Bối cảnh dai dẳng kéo dài

Trong một ứng dụng Java EE với các bean phiên trạng thái, bạn có thể thích bối cảnh để tồn tại nhiều lần gọi bean, vì bạn không muốn cam kết cho đến khi bean được đánh dấu để loại bỏ, phải không? Trong những trường hợp đó, bạn cần sử dụng ngữ cảnh liên tục mở rộng. Trong trường hợp này, ngữ cảnh liên tục được tạo khi nó cần lần đầu tiên, nhưng nó sẽ không trở nên vô hiệu cho đến khi bạn đánh dấu bean trạng thái để xóa.

@PersistenceContext(unitName="EmplService", type=PersistenceContextType.EXTENDED)

Điều này có nghĩa là, bất kể trường hợp của trình quản lý thực thể được đưa vào bean này trong các lệnh gọi tiếp theo của các phương thức bean phiên trạng thái, bạn có thể chắc chắn rằng bạn sẽ luôn truy cập cùng một ngữ cảnh và do đó, ngay cả các lệnh gọi tiếp theo cũng sẽ trả về cùng ví dụ, bởi vì nó là cùng một ngữ cảnh.

Ngoài ra, các thay đổi của bạn sẽ không được xả cho đến khi hạt đậu được đánh dấu để loại bỏ hoặc bạn xả chúng theo cách thủ công.

Ứng dụng được quản lý

Bạn luôn có thể khởi tạo theo cách thủ công nhà máy quản lý thực thể và người quản lý thực thể của bạn. Đây là những gì bạn thường làm trong một ứng dụng JSE, đúng không?

Đối với loại ứng dụng này, bạn thường không có vùng chứa để xử lý các giao dịch JTA, phải không? Vì vậy, bạn sử dụng các giao dịch tài nguyên-cục bộ và bạn chịu trách nhiệm thực hiện thủ công hoặc khôi phục các thay đổi.

Đối với loại ứng dụng này, khi bạn khởi tạo trình quản lý thực thể của mình, một ngữ cảnh sẽ tự động được đính kèm với nó.

Tùy thuộc vào ứng dụng của bạn, bạn có thể quyết định tạo một trình quản lý thực thể toàn cầu có vòng đời gắn liền với vòng đời của chính ứng dụng. Đó là một trình quản lý thực thể duy nhất cho toàn bộ vòng đời của ứng dụng. Trong trường hợp này, ngữ cảnh của bạn sẽ được tạo và hủy bằng trình quản lý thực thể của bạn.

Hoặc, bạn có thể tạo một người quản lý thực thể cho mỗi cuộc trò chuyện (tức là giao dịch) với người dùng ứng dụng của bạn. Phạm vi, trong trường hợp này, do bạn xác định, nhưng vẫn còn, ngữ cảnh của bạn sẽ được tạo và phá hủy với trình quản lý thực thể của bạn.


Câu trả lời tuyệt vời, nhưng tôi cần biết: mở và đóng EntityManager nhiều lần trong một phiên có chi phí hiệu suất cao hơn không? Khởi tạo và đóng chỉ một lần hoặc khởi tạo / sử dụng / đóng nó trong mọi thao tác xử lý cơ sở dữ liệu, cách tiếp cận nào là tốt nhất? "nó phụ thuộc" ok, nhưng phải có một sử dụng phù hợp hơn cho đa số các trường hợp sử dụng ..
tomrlh

4
@tomurlh Theo tôi thì chi phí tạo EntityManagerphải không đáng kể. Theo quan điểm của tôi, EntityManager chỉ là một phần trừu tượng để giải quyết đơn vị công việc của giao dịch hiện tại. Tôi tin rằng hoàn toàn ổn nếu tạo và hủy một trong mỗi giao dịch. Bây giờ, nó có những ý nghĩa khác, bởi vì các EntityManagermáy chủ như một bộ đệm ẩn giao dịch cho các thực thể của bạn và do đó, việc có phạm vi giao dịch được xác định rõ ràng và xử lý đúng cách với các thực thể có thể tận dụng bộ đệm này.
Edwin Dalorzo

Phương thức EntityManager.close đóng một trình quản lý thực thể để giải phóng ngữ cảnh tồn tại của nó Ngữ cảnh tồn tại là gì?
gstackoverflow

Điều này cũng có nghĩa là tùy thuộc vào cách bạn thiết kế các giao dịch của mình, bạn có thể kết thúc với nhiều hơn một ngữ cảnh. Bạn có thể giải thích làm thế nào?
gstackoverflow
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.