2012-03-29 33 views
14

Tôi có một bộ gồm @Service các hạt kế thừa chức năng cốt lõi từ một lớp trừu tượng. Tôi đã đánh dấu từng dịch vụ cấp dưới cụ thể bằng @Service@Transactional. Lớp siêu trừu tượng chứa phương thức điểm vào công khai cho từng dịch vụ này. Nói cách khác, tôi có một cái gì đó tương tự như sau:Quy tắc thừa kế Spring @Transactional

abstract class AbstractService { 

    public void process() { 
     // Do common initialisation code here 
     processSpecific(); 
     // Do common completion code here 
    } 

    abstract protected void processSpecific(); 
} 


@Service @Transactional 
public class FirstSpecificService extends AbstractService { 
    protected void processSpecific() { 
     // Do specific processing code here 
    } 
} 


@Service @Transactional 
public class SecondSpecificService extends AbstractService { 
    protected void processSpecific() { 
     // Do different specific processing code here 
    } 
} 

Các mã cụ thể trong mỗi dịch vụ sub-class bê tông làm cho nhiều cuộc gọi đến các lớp DAO để thay đổi cơ sở dữ liệu, trong đó có REQUIRED như công tác tuyên truyền giao dịch kiểu. Bây giờ với các dịch vụ được xác định như trên, tôi phát hiện ra rằng không có giao dịch hiện tại bên trong bất kỳ mã nào của các dịch vụ phụ lớp bê tông này, và mỗi cuộc gọi đến lớp DAO đã tạo một giao dịch mới, thực hiện các thay đổi, cam kết giao dịch và trả lại.

Tuy nhiên, nếu tôi chú thích các siêu lớp trừu tượng với @Transactional, sau đó một giao dịch tạo đúng cách, và các tiểu cuộc gọi đến các lớp DAO tất cả tham gia vào các giao dịch vãng lai.

Vì vậy, câu hỏi của tôi là, các quy tắc để kế thừa hành vi @Transactional là gì? Tại sao Spring không sử dụng @Transactional trên các dịch vụ phụ cấp cụ thể mà nó thực sự khởi tạo? Liệu các @Transactional cần phải được trên siêu hạng trong trường hợp này bởi vì đó là nơi mà các phương pháp nhập điểm công cộng là?

+0

Nhân tiện, tôi đã xem [tài liệu SpringSource có liên quan] (http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/htmlsingle/spring-framework -reference.html # transaction-declarative-annotations), nhưng điều đó dường như không bao gồm điều này. – DuncanKinnear

Trả lời

9

Từ các tài liệu giao dịch mùa xuân,

Lưu ý: Trong chế độ proxy (đó là mặc định), chỉ có phương pháp 'bên ngoài' các cuộc gọi đến trong thông qua proxy sẽ bị chặn. Điều này có nghĩa là 'tự gọi', nghĩa là 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 tế khi chạy ngay cả khi phương thức được gọi được đánh dấu bằng @Transactional!

Mặc dù bạn có @Transactional về triển khai cụ thể của bạn và bạn đang gọi phương thức xử lý thực sự giao dịch bằng chú thích của bạn, nhưng quá trình gọi processSpecific trên lớp phụ của bạn không giao dịch vì cuộc gọi nội bộ này.

Nhìn vào Dệt.

+0

Nhưng proxy sẽ không là một phiên bản của 'FirstSpecificService'? Trong trường hợp đó, hệ thống sẽ gọi phương thức 'process' bên ngoài của cá thể đó, và bản thân cá thể đó được đánh dấu là '@ Transactional'. Tôi hoàn toàn hiểu rằng các phương thức riêng tư hoặc được bảo vệ nội bộ được đánh dấu là '@ Transactional' sẽ không ảnh hưởng đến giao dịch, nhưng đó không phải là những gì tôi có. Toàn bộ bean của tôi được đánh dấu là '@ Transactional'. – DuncanKinnear

+0

Không, nó sẽ không được giao dịch nếu được gọi từ phương thức nội bộ. Để bắt đầu khi bạn gọi phương thức xử lý từ bên ngoài, cá thể proxy được kiểm soát giao dịch và khi phương thức xử lý gọi processSpecific, spring không biết về giao dịch khi việc cắt điểm được thực hiện trên đối tượng proxy không nằm trong processSpecific phụ phương pháp. Chúng tôi đã có cùng một vấn đề và chúng tôi đã thêm thời gian tải dệt và mọi thứ hoạt động. – Kathir

+0

Cab bạn giải thích 'thời gian tải dệt' đối với ví dụ của tôi ở trên. Làm thế nào nó sẽ thay đổi mã của các dịch vụ ví dụ (contrived)? – DuncanKinnear

1

Bạn đã đọc phần về transaction propagation và cách cấu hình có thể được định cấu hình bằng cách sử dụng @Transactional?

Một lĩnh vực quan tâm khác là Spring khuyên bạn nên annotate concrete classes (như trái ngược với giao diện chú thích).

+0

Có, như đã nêu ở trên, tôi đã đọc tất cả các phần của tài liệu và không có phần nào trong số này dường như áp dụng trong trường hợp này. Siêu lớp trừu tượng của tôi là ** không ** một giao diện, nó là mã được thừa kế bởi lớp con cụ thể thực tế. Có lẽ bạn có thể trích dẫn phần tài liệu mà bạn nghĩ áp dụng cho ví dụ của tôi. – DuncanKinnear

+1

Nếu bạn muốn đảm bảo rằng DAO của bạn luôn tham gia vào một giao dịch hiện có (được khởi xướng bởi dịch vụ của bạn), bạn nên cấu hình DAOs thành @Transactional (propagation = [Propagation.MANDATORY] (http://static.springsource.org /spring/docs/3.1.x/javadoc-api/org/springframework/transaction/annotation/Propagation.html#MANDATORY)), vì sử dụng [REQUIRED] (http://static.springsource.org/spring/docs/3.1 .x/javadoc-api/org/springframework/transaction/annotation/Propagation.html # REQUIRED) sẽ tạo giao dịch mới nếu không tồn tại. – matsev

+0

Vâng, đó sẽ là một cách để chúng tôi nắm bắt những vấn đề này trong tương lai, nhưng nó vẫn không giải thích những quy tắc thừa kế là gì. – DuncanKinnear

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