2014-05-23 13 views
5

Tôi đang phát triển một ứng dụng JPA (có ngủ đông), và tôi đang đấu tranh với tính năng AutoFlush.Ngăn chặn tuôn ra của EntityManager khi chọn một dữ liệu nhất định

Theo mặc định, bất cứ khi nào chúng tôi xử lý truy vấn trên bất kỳ thực thể nào, toàn bộ EntityManager bị xóa. Điều này là ok trong hầu hết các trường hợp: Chúng tôi muốn JPA xử lý các truy vấn đối với một DB cập nhật.

Tuy nhiên, điều đó xảy ra là chúng tôi cũng lưu trữ một số thông số chức năng trong DB của chúng tôi. Điều này hoàn toàn tách biệt với mô hình kinh doanh cốt lõi của chúng tôi, và chúng tôi không muốn chọn các thông số mà chúng tôi đã xóa EM: Lấy thông số có thể xảy ra khá sâu trong quá trình và chúng tôi mất kiểm soát xả EM khi chúng tôi biết; .

Thật vậy, điều này gây ra một số ngoại lệ ràng buộc DB: Mô hình dữ liệu không nhất quán (ở giữa quy trình) và chọn tham số buộc thực thi mô hình dữ liệu này.

Tôi đang cân nhắc việc thêm một thực thể thứ haiManager, chỉ là thông số, nhưng tôi thấy nó quá mức cần thiết.

Có thể giải quyết dễ dàng hơn không? Với mức cô lập trên thông số DAO, để các tham số được xử lý trong một giao dịch riêng biệt?

Trả lời

1

I. Nếu bạn sử dụng JTA:

  1. Hãy thử sử dụng một giao dịch mới trong ParametersDAO. Bằng cách này, các thực thể được quản lý của bạn trong dịch vụ bên ngoài sẽ không được quản lý trong DAO (IMHO!). Điểm bất lợi là khi số tiền trả về ParametersDAO của bạn, giao dịch sẽ thực hiện (nếu điều đó không được mong muốn, bạn có thể sử dụng EJB Statefull, nhưng điều này có vẻ như quá mức đối với tôi).
  2. Nếu không, có một EntityManager thứ hai không có vẻ như là quá mức cần thiết đối với tôi.

II. Nếu bạn sử dụng NGUỒN-ĐỊA PHƯƠNG:

Nếu bạn đang ở trong một môi trường ứng dụng-Quản lý (transaction-type="RESOURCE_LOCAL"), chỉ cần nhận được một EntityManager từ EntityManagerFactory (tương tự với việc có một thứ hai EntityManager).

3

Điều này có thể được giải quyết bằng các giao dịch JTA, nhưng bạn cần một người quản lý giao dịch JTA. Nếu bạn đang chạy trong một máy chủ ứng dụng Java EE thì bạn đã có hỗ trợ JTA. Nếu bạn chạy một ứng dụng dựa trên Spring, bạn cần bao gồm một TM độc lập, như Bitronix.

JTA sau đó cho phép bạn tranh thủ nhiều kết nối ngay cả đối với cùng một DB (nhưng với nhiều nguồn dữ liệu từ cùng một luồng) trong một giao dịch toàn cầu duy nhất. Vì vậy, bạn quản lý thực thể sẽ tranh thủ một kết nối và sau đó bạn có thể mở một kết nối mới từ hồ bơi kết nối XA của bạn (được cung cấp bởi người quản lý giao dịch JTA của bạn, như Bitronix) và lưu các thông số chức năng .

Hai kết nối được liệt kê này sẽ bị cô lập, do đó, các thay đổi trong một kết nối sẽ không khả dụng trong giây cho đến sau khi giao dịch được thực hiện.

Nếu các thông số chức năng không cần phải được lưu thông qua JPA, sẽ dễ dàng hơn khi sử dụng Spring JDBC cho tác vụ này. Nếu không, bạn cần hai người quản lý thực thể và điều đó sẽ làm phức tạp thêm cài đặt của bạn.

+0

Tôi thực sự tò mò làm thế nào bạn "có thể mở một kết nối mới từ hồ bơi kết nối XA của bạn", bạn có thể cung cấp thêm chi tiết về điều đó không ?. PS: Nó có thể là một giải pháp thú vị, nhưng đến nay không sử dụng các API chuẩn. –

+0

Kiểm tra [HibernateSQLStatementCountTest] của tôi (https://github.com/vladmihalcea/vladmihalcea.wordpress.com/blob/master/hibernate-facts/src/test/java/com/vladmihalcea/HibernateSQLStatementCountTest.java). Nó mở rộng 2 nguồn dữ liệu: testDataSource và otherDataSource trong cùng một giao dịch cho cùng một DB, mỗi một với kết nối riêng của nó. DEBUG [main]: bttPreparer - chuẩn bị tài nguyên một XAResourceHolderState với uniqueName = otherDataSource DEBUG [main]: bttPreparer - chuẩn bị tài nguyên một XAResourceHolderState với uniqueName = testDataSource –

+0

Đó không phải là những gì bạn mô tả trong câu trả lời của bạn: trên github bạn có hai khác nhau ' DataSource's và trong câu trả lời của bạn, bạn đang nói về việc lấy hai kết nối cho cùng một 'DataSource'. –

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