2012-06-27 26 views
5

Mã sau được thực thi bất cứ khi nào tôi muốn tồn tại bất kỳ thực thể nào. Mọi thứ dường như hoạt động tốt nhưng tôi không hiểu nó hoạt động như thế nào!Cách các giao dịch JPA hoạt động

EntityManager em = getEntityManager(); 
EntityTransaction userTransaction = em.getTransaction(); 
userTransaction.begin(); 
em.persist(ent); 
userTransaction.commit(); 

EntityManager ở trên là một trường hợp duy nhất được chia sẻ cho toàn bộ ứng dụng. Sau khi bắt đầu giao dịch; Tôi chỉ nói em.persist (thực thể) .. Làm thế nào để hibernate biết nó thuộc về giao dịch nào!

Giả sử có 10 người dùng đồng thời trên ứng dụng của tôi và tất cả 10 chủ đề thực thi mã trên. Vì vậy, 10 giao dịch độc lập đang được tạo và cam kết. Nhưng tất cả 10 thực thể khác nhau tôi không liên kết chúng với các giao dịch tương ứng; JPA có thể làm việc như thế nào!

Dựa trên câu trả lời; chúng tôi có dưới đây; chúng ta có nói rằng chúng ta nên có một cá thể EntityManager cho mỗi luồng không? Sẽ không phải là một giết trên máy chủ! Chúng ta có nên gộp chung những trường hợp này không? Nó sẽ không bằng một lần nữa thực hiện loại kết nối tổng hợp?

+2

Ý của bạn là "giao dịch" nào? Một EM có một giao dịch (cục bộ) duy nhất bất cứ lúc nào; nó không có nhiều. Chia sẻ một EM duy nhất trên nhiều luồng là một công thức cho các vấn đề, vì nó không đảm bảo an toàn cho luồng. – DataNucleus

+0

http://docs.jboss.org/hibernate/orm/4.0/hem/en-US/html/transactions.html Một EntityManagerFactory là một đối tượng tạo chủ đề, tốn kém để tạo ra được chia sẻ bởi tất cả các luồng ứng dụng. Nó được tạo ra một lần, thường là khi khởi động ứng dụng. Một EntityManager là một đối tượng không an toàn, rẻ tiền nên được sử dụng một lần, cho một quy trình nghiệp vụ đơn lẻ, một đơn vị công việc duy nhất, và sau đó bị loại bỏ – Deepak

+0

Đọc thêm; những gì tôi hiểu là tạo ra EntityManager là trọng lượng nhẹ nhưng vẫn không phải là trọng lượng rất nhẹ cho mỗi hoạt động DB nhỏ mà chúng tôi tạo ra. Giải pháp được đề xuất là tạo EM cho mỗi yêu cầu. Vì vậy, có vẻ như nó phải ở cấp ThreadLocal. – Deepak

Trả lời

4

Nó hoạt động bởi vì bạn đủ may mắn. Đủ may mắn có nghĩa là cam kết và bắt đầu được gọi theo thứ tự đúng - vô tình.

Bạn sử dụng cá thể đơn của trình quản lý thực thể từ nhiều chuỗi. Đó là điều sai trái để làm, bởi vì nó không được đảm bảo là luồng an toàn. Truy cập vào giao dịch cấp tài nguyên thông qua EntityTransaction được ràng buộc với cá thể quản lý thực thể, chứ không phải cho luồng.

Vì vậy, kết quả là bạn đang chia sẻ cùng một EntityTransaction và sử dụng nó may mắn serially cho nhiều giao dịch. Sử dụng nó serially để strart và kết thúc nhiều giao dịch là tốt, nhưng sử dụng nó từ nhiều chủ đề là không.

Trong tham chiếu ngủ đông (4.1.4) được lưu vào trường thể hiện tx trong lớp AbstractEntityManageImpl, nhưng đó chỉ là chi tiết triển khai.

+0

là chúng ta nói rằng chúng ta nên có một đối tượng EntityManager cho mỗi chủ đề? Sẽ không phải là một giết trên máy chủ! Chúng ta có nên gộp chung những trường hợp này không? Nó sẽ không bằng một lần nữa thực hiện loại kết nối tổng hợp? – Deepak

+2

EntityManager là đối tượng khá sáng tạo, EntityManagerFactory có trọng lượng nặng. Không có lý do để bắt đầu quản lý thực thể hồ bơi. –

+0

Tôi hiểu EntityManager không phải là chủ đề an toàn mà chúng ta nên tạo các đối tượng mới. Nhưng chúng ta cần phải tạo EntityManagers mới cho truy vấn chọn quá (mà chúng tôi không bắt đầu bất kỳ giao dịch) .. Sẽ không được quá mức cần thiết? – Deepak

1

Giao dịch được liên kết với luồng hiện tại bằng cách nào đó, sử dụng biến ThreadLocal.

+1

Vì vậy, là ở trên thiết kế hoàn hảo hay không! Tôi vẫn còn bối rối ! – Deepak

+0

Tất cả phụ thuộc vào cách bạn có được một thể hiện của EntityManager. Nếu nó được tiêm trong các EJB hoặc trong các bean Spring (như được giải thích trong tài liệu Spring), EntityManager thực ra là một proxy để thực thi EntityManager thực tế. Nếu không, hãy xem câu trả lời của Mikko Maunu. –

+1

Tôi hiểu EntityManager không phải là chủ đề an toàn mà chúng ta nên tạo các đối tượng mới. Nhưng chúng ta cần phải tạo EntityManagers mới cho truy vấn chọn quá (mà chúng tôi không bắt đầu bất kỳ giao dịch) .. Sẽ không được quá mức cần thiết? – Deepak

0

tôi khuyên bạn nên hiểu như thế nào JTA công trình bất kể Hibernate - nó khá quan trọng đối với bạn để hiểu
Bên cạnh đó, đọc về các giao dịch chứa được quản lý và giao dịch bean được quản lý.
Nếu bạn đang làm việc trong một giao dịch do container quản lý, bạn có thể chỉ định bean bạn đang tiêm EntityManager vào phạm vi giao dịch -
chẳng hạn - nếu phạm vi được yêu cầu, điều đó có nghĩa là nếu một bean khác gọi bean này, và không phải trong ngữ cảnh giao dịch, một giao dịch mới sẽ được mở. Nếu một giao dịch đã tồn tại, thì bạn sẽ sử dụng cùng một giao dịch. Điều quan trọng là phải hiểu điều này, vì các giao dịch là một nguồn tài nguyên đắt tiền trong hệ thống của bạn.

Một đối tượng giao dịch có liên quan đến ThreadLocal, tuy nhiên, thread khác có thể tiếp tục một giao dịch bị đình chỉ, phụ thuộc vào việc thực hiện các TransactionManager của bạn (Tôi đang nói về JBossTransactionManager)

+1

Anh ấy đang sử dụng các giao dịch địa phương tại đây, như được hiển thị bằng lệnh gọi hàm em.getTransaction(). Và trong trường hợp đó chỉ có 1 giao dịch cho mỗi EM, và thiết kế của anh ta là thiếu sót. – DataNucleus

5

Đang sử dụng ThreadLocal biến cho Giao dịch.

Xem thêm tài liệu cho UserTransaction:

bắt đầu()
Tạo một giao dịch mới và kết hợp nó với các chủ đề hiện hành.

Bạn không nên chia sẻ EntityManager dù không đảm bảo an toàn cho chuỗi.

Tuy nhiên nếu bạn đang tiêm nó trong một EJB, bạn không phải lo lắng về thread-an toàn: http://www.adam-bien.com/roller/abien/entry/is_in_an_ejb_injected

Nếu bạn đang sử dụng Spring để bơm nó, bạn sẽ nhận được một proxy thread-safe: http://static.springsource.org/spring/docs/3.1.1.RELEASE/spring-framework-reference/html/orm.html#orm-jpa-straight

Mặc dù EntityManagerMô hình của nhà sản xuất là an toàn chủ đề, nhưng đối tượng EntityManager thì không. Trình đối tượng JPA EntityManager được tiêm giống như một EntityManager được lấy từ môi trường JNDI của máy chủ ứng dụng, như được định nghĩa bởi đặc tả JPA. Nó ủy nhiệm tất cả các cuộc gọi đến EntityManager giao dịch hiện tại, nếu có; nếu không, nó rơi trở lại một EntityManager mới được tạo cho mỗi hoạt động, có hiệu lực làm cho việc sử dụng thread-safe của nó.

+1

Điều đó không đúng với ít nhất cho việc triển khai Hibernate.Tại sao nó sẽ sử dụng ThreadLocal trong đối tượng mà là ment được sử dụng từ thread đơn? –

+1

Dường như phụ thuộc vào nơi bạn sử dụng nó: http://stackoverflow.com/questions/8603478/does-jboss-handle-managed-entity-manager-concurrency-issues-for-me – Sandro

+0

Không, việc tiêm không tự tạo ra ví dụ duy nhất của chuỗi trình quản lý thực thể an toàn. Thay vào đó, truy cập tuần tự hóa vào nhà cung cấp ejb bằng cách đảm bảo rằng nó không được sử dụng đồng thời từ nhiều luồng. Bạn cũng có thể sử dụng tra cứu jndi thay vì tiêm và đảm bảo an toàn luồng theo hợp đồng ejb. –

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