javax.transaction.Transactional so với org.springframework.transaction.annotation.Transactional


161

Tôi không hiểu sự khác biệt thực sự giữa chú thích javax.transaction.Transactionalorg.springframework.transaction.annotation.Transactional?

org.springframework.transaction.annotation.Transactionalmột phần mở rộng của javax.transaction.Transactionalhay chúng có ý nghĩa hoàn toàn khác? Khi nào nên sử dụng mỗi loại? Spring @Transactinaltrong lớp dịch vụ và javax trong DAO?

Cảm ơn vì đã trả lời.

Câu trả lời:


135

Spring đã xác định chú thích Giao dịch của riêng mình để làm cho các phương thức Spring bean giao dịch, nhiều năm trước.

Java EE 7 cuối cùng đã làm được điều tương tự và giờ đây cho phép các phương thức bean CDI được giao dịch, ngoài các phương thức EJB. Vì vậy, kể từ Java EE 7, nó cũng định nghĩa chú thích Giao dịch của riêng mình (rõ ràng là nó không thể sử dụng lại Spring).

Trong ứng dụng Java EE 7, bạn sẽ sử dụng chú thích Java EE.

Trong ứng dụng Spring, bạn sẽ sử dụng chú thích Spring.

Cách sử dụng của chúng giống nhau: thông báo cho vùng chứa (Java EE hoặc Spring) rằng một phương thức là giao dịch.


31
Hơn thế nữa: để thống trị vũ trụ, Spring cũng đã thêm hỗ trợ ngầm javax.transaction.Transactionalđể giờ đây người ta có thể sử dụng nó trong các ứng dụng Spring mà không cần bất kỳ hành động bổ sung nào. IMO, đây là một quyết định khá tồi từ quan điểm thiết kế , vì theo kinh nghiệm của tôi, rất nhiều nhà phát triển đã nhầm lẫn hai điều này một cách vô ý thức trong mã của họ, dẫn đến các vấn đề sau đó.
Yuriy Nakonechnyy

16
Bên cạnh đó, org.springframework.transaction.annotation.Transactionalcung cấp thêm nhiều lựa chọn (như readOnly, timeout) hơnjavax.transaction.Transactional
pierrefevrier

1
@yura, bạn đã quan sát thấy những vấn đề gì?
Lee Chee Kiam

1
@LeeCheeKiam xin vui lòng xem hai câu trả lời dưới đây
Yuriy Nakonechnyy

53

Một điểm khác biệt nữa là cách Spring xử lý các chú thích @Transactional

  • org.springframework.transaction.annotation.Transactional luôn được tính đến
  • javax.transaction.Transactional chỉ được tính đến khi có giao dịch EJB3. Sự hiện diện của các giao dịch EJB3 được thực hiện bằng cách kiểm tra xem lớp javax.ejb.TransactionAttributecó sẵn trong classpath hay không (từ phiên bản 2.5.3 đến 3.2.5). Vì vậy, bạn có thể kết thúc với việc các chú thích của bạn không được tính đến nếu chỉ javax.transaction.Transactionalnằm trong classpath của bạn và không javax.ejb.TransactionAttribute. Đây có thể là trường hợp nếu bạn đang làm việc với Hibernate: hibernate-core (4.3.7.Final) phụ thuộc vào jboss-transaction-api_1.2_spec (1.0.0.Final), không cung cấp javax.ejb.TransactionAttribute.


nó không phải lúc nào cũng được lấy, nếu nó nằm trên một phương thức riêng tư thì nó sẽ không được lấy.
strash

37

Hãy cẩn thận, (sự cố này đã xảy ra trong tomcat),

Nếu ứng dụng của bạn là ứng dụng web SPRING và bạn đang sử dụng cơ chế xử lý giao dịch của Spring @org.springframework.transaction.annotation.Transactional, thì đừng kết hợp nó với javax.transaction.Transactional.

Đó là Luôn sử dụng, @org.springframework.transaction.annotation.Transactionaltrong một ứng dụng mùa xuân một cách nhất quán.

Nếu không, chúng tôi có thể gặp phải lỗi này,

org.springframework.orm.jpa.JpaSystemException: commit failed; nested exception is org.hibernate.TransactionException: commit failed

........

Caused by: java.sql.SQLException: Protocol violation: [0]

1
Lưu ý: câu trả lời này là một trường hợp đặc biệt trong câu trả lời của tôi
Jidehem

8

Phạm vi giao dịch khai báo

Cả @Transactionchú thích Spring và JPA đều cho phép bạn xác định phạm vi của một giao dịch ứng dụng nhất định.

Vì vậy, nếu một phương thức dịch vụ được chú thích bằng @Transactionalchú thích, nó sẽ chạy trong ngữ cảnh giao dịch. Nếu phương thức dịch vụ sử dụng nhiều DAO hoặc Kho lưu trữ, tất cả các thao tác đọc và ghi sẽ được thực hiện trong cùng một giao dịch cơ sở dữ liệu.

Mùa xuân @Transactional

Các org.springframework.transaction.annotation.Transactionalchú thích đã có sẵn từ phiên bản 1.2 của Spring framework (khoảng năm 2005), và nó cho phép bạn thiết lập các thuộc tính giao dịch sau:

  • isolation: mức cô lập cơ sở dữ liệu cơ bản
  • noRollbackFornoRollbackForClassName: danh sách các Exceptionlớp Java có thể được kích hoạt mà không kích hoạt việc khôi phục giao dịch
  • rollbackForrollbackForClassName: danh sách các Exceptionlớp Java kích hoạt một giao dịch khôi phục khi được ném
  • propagation: kiểu truyền giao dịch do PropagationEnum đưa ra . Ví dụ: nếu ngữ cảnh giao dịch có thể được kế thừa (ví dụ, REQUIRED) hoặc một ngữ cảnh giao dịch mới nên được tạo (ví dụ REQUIRES_NEW:) hoặc nếu một ngoại lệ nên được ném nếu không có bối cảnh giao dịch nào (ví dụ, MANDATORY) hoặc nếu một ngoại lệ nên được ném nếu bối cảnh giao dịch hiện tại được tìm thấy (ví dụ NOT_SUPPORTED:).
  • readOnly: liệu giao dịch hiện tại chỉ nên đọc dữ liệu mà không áp dụng bất kỳ thay đổi nào.
  • timeout: ngữ cảnh giao dịch sẽ được phép chạy trong bao nhiêu giây cho đến khi một ngoại lệ thời gian chờ được đưa ra.
  • valuehoặc transactionManager: tên của Spring TransactionManagerbean sẽ được sử dụng khi ràng buộc ngữ cảnh giao dịch.

Java EE @Transactional

Các javax.transaction.Transactionalchú thích đã được bổ sung bởi các đặc điểm kỹ thuật Java EE 7 (khoảng năm 2013). Vì vậy, chú thích Java EE được thêm vào muộn hơn 8 năm so với phiên bản Spring của nó.

Java EE @Transactionalchỉ định nghĩa 3 thuộc tính:

  • dontRollbackOn: danh sách các Exceptionlớp Java có thể được kích hoạt mà không kích hoạt việc khôi phục giao dịch
  • rollbackOn: danh sách các Exceptionlớp Java kích hoạt một giao dịch khôi phục khi được ném
  • value: chiến lược truyền bá, được đưa ra bởi TxTypeEnum. Ví dụ: nếu ngữ cảnh giao dịch có thể được kế thừa (ví dụ REQUIRED:) hoặc một ngữ cảnh giao dịch mới nên được tạo (ví dụ REQUIRES_NEW:) hoặc nếu một ngoại lệ nên được ném nếu không có ngữ cảnh giao dịch nào (ví dụ, MANDATORY) hoặc nếu một ngoại lệ nên được ném nếu bối cảnh giao dịch hiện tại được tìm thấy (ví dụ NOT_SUPPORTED:).

Chọn cái nào?

Nếu bạn đang sử dụng Spring hoặc Spring Boot, hãy sử dụng @Transactionalchú thích Spring , vì nó cho phép bạn định cấu hình nhiều thuộc tính hơn so với @Transactionalchú thích Java EE .

Nếu bạn đang sử dụng Java EE một mình và bạn triển khai ứng dụng của mình trên máy chủ ứng dụng Java EE, thì hãy sử dụng @Transactionalchú thích Java EE .

Để biết thêm chi tiết về cấu hình mức cô lập khác nhau như thế nào khi sử dụng các @Transactionalđịnh nghĩa Spring hoặc Java EE , hãy xem bài viết này .


Chú thích Java / Jakarta EE @Transactional có hoạt động cho privatecác phương thức không?
Dina Bogdan

1
Hầu như không. Ranh giới giao dịch sẽ bắt đầu khi gọi một dịch vụ từ một lớp khác, như web hoặc bộ lập lịch.
Vlad Mihalcea

Trên thực tế, tôi đã có một phương thức ủy quyền trong cùng một lớp với phương thức được chú thích bằng @Transactional. Tôi biết rằng tôi chỉ có thể di chuyển chú thích sang phương thức ủy quyền này, nhưng tôi tò mò về điều này và tôi không tìm thấy bất kỳ thứ gì trên web.
Dina Bogdan

Các phương thức riêng tư không được tính. Chỉ các phương thức liên dịch vụ mới được tính cho các quy tắc truyền .
Vlad Mihalcea
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.