2010-06-25 23 views

Trả lời

83

Từ http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

khuyến nghị Nhóm nghiên cứu của Spring là bạn chỉ chú thích các lớp bê tông với @Transactional chú thích, như trái ngược với chú thích giao diện. Bạn chắc chắn có thể đặt chú thích @Transactional trên giao diện (hoặc một phương thức giao diện), nhưng điều này sẽ chỉ hoạt động như bạn mong đợi nếu bạn đang sử dụng proxy dựa trên giao diện. Thực tế là chú thích là không được thừa hưởng có nghĩa là nếu bạn đang sử dụng proxy dựa trên lớp thì cài đặt giao dịch sẽ không được cơ sở hạ tầng proxy lớp dựa trên lớp và đối tượng sẽ không được bao bọc trong proxy giao dịch. xấu). Vì vậy, hãy làm theo lời khuyên của nhóm Spring và chỉ chú thích các lớp cụ thể (và các phương thức của các lớp cụ thể) với chú thích @Transactional.

Lưu ý: Vì cơ chế này dựa trên proxy, chỉ các cuộc gọi phương thức 'bên ngoài' đến thông qua proxy sẽ bị chặn. Điều này có nghĩa là 'tự viện dẫn', tức là một phương thức trong đối tượng đích gọi một số phương thức khác của đối tượng đích, sẽ không dẫn đến giao dịch thực sự khi chạy ngay cả khi phương thức được gọi được đánh dấu bằng @Transactional!

(Nhấn mạnh thêm vào câu đầu tiên, nhấn mạnh khác từ bản gốc.)

+0

Big +1 BTW, tôi lấy tự do làm trích dẫn câu trích dẫn, vì vậy mọi người không bối rối, và thêm lại chữ in nghiêng và từ bản gốc. –

+0

@ T.J. Crowder - Tuyệt vời như thế nào câu trả lời khác thay đổi. thx, NP –

+0

Tôi đã đọc tuyên bố này trước đây trong Spring docu, nhưng tôi vẫn không thể hiểu tại sao cài đặt _transaction sẽ không được cơ sở hạ tầng proxy lớp dựa trên lớp? Cá nhân tôi nghĩ, đây chỉ là giới hạn triển khai Spring, chứ không phải vấn đề cơ sở hạ tầng proxy cơ bản. –

0

Đưa nó trên giao diện là tốt miễn tất cả các cơ quan thực hiện dự đoán được chăm sóc IFC của bạn về dữ liệu TX (giao dịch không phải là vấn đề mà chỉ cần xử lý cơ sở dữ liệu). Nếu phương pháp không quan tâm đến TX (nhưng bạn cần phải đặt nó ở đó cho Hibernate hoặc bất cứ điều gì), đặt nó trên impl.

Ngoài ra, nó có thể là một chút tốt hơn để đặt @Transactional về các phương pháp trong giao diện:

public interface FooService { 
    @Transactional(readOnly = true) 
    void doSmth(); 
} 
7

Bạn có thể đặt chúng trên giao diện nhưng được cảnh báo rằng giao dịch có thể không kết thúc xảy ra trong một số trường hợp. Xem mũi thứ hai trong Secion 10.5.6 của các tài liệu Xuân:

Xuân khuyến cáo rằng bạn chỉ chú thích các lớp bê tông (và phương pháp của lớp bê tông) với chú thích @Transactional, như trái ngược với chú thích giao diện. Bạn chắc chắn có thể đặt chú thích @Transactional trên một giao diện (hoặc một phương thức giao diện), nhưng điều này chỉ hoạt động như bạn mong đợi nếu bạn đang sử dụng proxy dựa trên giao diện. Thực tế là chú thích Java không được kế thừa từ giao diện có nghĩa là nếu bạn đang sử dụng proxy dựa trên lớp (proxy-target-class = "true") hoặc khía cạnh dựa trên dệt (mode = "aspectj"), thì cài đặt giao dịch là không được công nhận bởi cơ sở hạ tầng proxy và dệt, và đối tượng sẽ không được bao bọc trong proxy giao dịch, điều này sẽ rất tệ.

Tôi khuyên bạn nên đưa chúng vào triển khai vì lý do này.

Ngoài ra, với tôi, các giao dịch có vẻ như một chi tiết triển khai nên chúng phải ở trong lớp triển khai. Hãy tưởng tượng có việc triển khai trình bao bọc để ghi nhật ký hoặc triển khai thử nghiệm (mocks) mà không cần phải giao dịch.

6

Spring recommendation là bạn chú thích các triển khai cụ thể thay vì một giao diện. Việc sử dụng chú thích trên giao diện không chính xác, bạn chỉ có thể lạm dụng tính năng đó và vô tình bỏ qua tuyên bố @Transaction của mình.

Nếu bạn đã đánh dấu một cái gì đó giao dịch trong một giao diện và sau đó tham khảo một trong các lớp triển khai của nó ở nơi khác trong mùa xuân, không rõ ràng đối tượng mà mùa xuân tạo sẽ không tôn trọng chú thích @Transactional.

Trong thực tế nó trông giống như sau:

public class MyClass implements MyInterface { 

    private int x; 

    public void doSomethingNonTx() {} 

    @Transactional 
    public void toSomethingTx() {} 

} 
2

Hỗ trợ @Transactional trên các lớp bê tông:

Tôi thích kiến ​​trúc sư một giải pháp trong 3 phần nói chung: một API, một Im plementation và một trang web (nếu cần). Tôi cố gắng hết sức để giữ cho API càng nhẹ/đơn giản/POJO càng tốt bằng cách giảm thiểu các phụ thuộc. Nó đặc biệt quan trọng nếu bạn chơi nó trong một môi trường phân phối/tích hợp, nơi bạn phải chia sẻ các API rất nhiều.

Đưa @Transactional yêu cầu thư viện Spring trong phần API, IMHO không hiệu quả. Vì vậy, tôi muốn thêm nó vào trong thực hiện nơi giao dịch đang chạy.

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