2012-06-12 33 views
13

Tôi đang sử dụng EclipseLink 2.3.0. Tôi có một phương pháp mà tôi đang gọi từ một thử nghiệm đơn vị (vì thế bên ngoài của một container, không JTA) trông như thế này:JPA/EclipseLink: EntityManager.getTransaction() có tạo giao dịch mới hoặc trả lại giao dịch đang hoạt động không?

EntityManager em = /* get an entity manager */; 
em.getTransaction().begin(); 
// make some changes 
em.getTransaction().commit(); 

Những thay đổi đã không được tồn cơ sở dữ liệu, và nhìn này cho một thời gian dài và cuối cùng nhận ra rằng EntityManager.getTransaction() thực sự trả về một EntityTransaction MỚI, chứ không phải là cùng một trong cả hai cuộc gọi. Hiệu ứng là cuộc gọi đầu tiên tạo một giao dịch mới và bắt đầu cuộc gọi đó và cuộc gọi thứ hai tạo ra giao dịch KHÁC và cam kết nó. Bởi vì giao dịch đầu tiên không bao giờ được cam kết, các thay đổi sẽ không được lưu. Chúng tôi xác nhận này như thế này:

log.info(em.getTransaction().toString()); 
log.info(em.getTransaction().toString()); 

nào dẫn đến các thông điệp ghi:

INFO: org.ecl[email protected]1e34f445 
INFO: org.ecl[email protected]706a4d1a 

Hai xác minh rằng có hai trường hợp khác nhau khác nhau đối tượng ID của. Thay đổi mã này:

EntityManager em = /* get an entity manager */; 
EntityTransaction tx = em.getTransaction(); 
tx.begin(); 
// make some changes 
tx.commit(); 

... khắc phục được sự cố. Bây giờ khi tôi chạy mã, tôi thấy các câu lệnh SQL được tạo ra để thực hiện công việc cơ sở dữ liệu và tìm trong cơ sở dữ liệu, dữ liệu đã được thay đổi.

Tôi hơi ngạc nhiên bởi kết quả này, vì tôi đã thấy nhiều ví dụ mã trực tuyến (đối với JPA nói chung và EclipseLink cụ thể) đề xuất mã chúng tôi sử dụng để quản lý giao dịch. Tôi đã tìm kiếm rất nhiều thông tin về điều này nhưng không tìm thấy gì cả. Vì vậy những gì đang xảy ra?

Tôi đã xem thông số JPA để biết điều gì đó chỉ định chính xác những gì getTransaction() thực hiện và không cụ thể nếu giao dịch mới hoặc giống nhau. Có một thiết lập trong persistence.xml điều khiển này? Có phải hành vi cụ thể đối với từng triển khai của thông số JPA không?

Cảm ơn bạn rất nhiều vì đã có bất kỳ thông tin hoặc hướng dẫn nào.

Trả lời

1

Thông số JPA (xem đoạn 7.5.4) có các ví dụ rõ ràng cho thấy việc sử dụng getTransaction() để bắt đầu và cam kết giao dịch. Vì vậy, mã của bạn nên được tốt.

Thử nghiệm của bạn cho thấy bạn nhận được hai đối tượng khác nhau, nhưng điều đó không có nghĩa là cùng một giao dịch không được sử dụng. Có lẽ đối tượng trả về chỉ là một số proxy cho một đối tượng giao dịch thực, đơn lẻ.

Hoặc có thể giao dịch được thực hiện hoặc được khôi phục bên trong mã bị ẩn dưới // make some changes.

+1

Có lẽ tôi phải rõ ràng hơn - mã tôi đăng KHÔNG hoạt động. Tôi đã chỉnh sửa câu hỏi để làm rõ. –

+0

Tôi hiểu điều đó. Quan điểm của tôi là nó * nên * làm việc, vì đặc tả JPA chứa các mẫu mã whet 'em.getTransaction()' được sử dụng để bắt đầu và cam kết giao dịch. Vì vậy, nó phải là một lỗi trong EclipseLink, trừ khi, như tôi đã nói, mã giữa bắt đầu và cam kết đã cam kết hoặc hoàn nguyên giao dịch. Câu trả lời của tôi không phải là giải pháp cho vấn đề của bạn, nhưng xác nhận rằng mã sẽ hoạt động. Tôi đề nghị nộp một lỗi cho EclipseLink. –

5

Sử dụng getTransaction() hoạt động trong JPA và trong EclipseLink (đây là cách thử nghiệm của chúng tôi hoạt động).

Tôi đoán bạn đang làm điều gì đó rất kỳ quặc.

Bạn đang sử dụng Spring hay một lớp khác? Vui lòng bao gồm toàn bộ mã và persistence.xml cho thử nghiệm của bạn. Đảm bảo rằng bạn không sử dụng JTA trong persistence.xml của bạn.

+0

getTransaction() nên ném một IllegalStateException nếu được gọi trên trình quản lý thực thể JTA. –

+0

Không có Spring, không có JTA, điều này đang được gọi từ kiểm tra JUnit bên ngoài vùng chứa. Mã trong "thực hiện một số thay đổi" là 4 dòng, tạo một đối tượng mới, thiết lập một giá trị số nguyên cho nó, hợp nhất và tuôn ra. Tôi sẽ tạo một ví dụ chưng cất khi tôi nhận được một phút. Có lẽ đây là lỗi EclipseLink. –

0

Bạn đã từng sử dụng persist before commit:?

Employee employee = new Employee("Samuel", "Joseph", "Wurzelbacher"); 
    em.getTransaction().begin(); 
    em.persist(employee); 
    em.getTransaction().commit(); 
Các vấn đề liên quan