sách gpt4 ai đã đi

Giải quyết vấn đề chú thích @Transaction gây ra lỗi chuyển đổi động và thay đổi cơ sở dữ liệu

In lại Tác giả:qq735679552 Thời gian cập nhật: 2022-09-27 22:32:09 37 4
mua khóa gpt4 Nike

CFSDN nhấn mạnh vào việc tạo ra giá trị thông qua mã nguồn mở. Chúng tôi cam kết xây dựng một nền tảng chia sẻ tài nguyên để mọi người làm CNTT có thể tìm thấy thế giới tuyệt vời của riêng mình tại đây.

Bài đăng trên blog CFSDN này giải quyết vấn đề chú thích @Transaction khiến việc chuyển đổi động và thay đổi cơ sở dữ liệu bị lỗi. Bài đăng được tác giả thu thập và sắp xếp. Nếu bạn quan tâm đến bài viết này, hãy nhớ thích nó.

@Chú thích giao dịch khiến việc chuyển đổi động để thay đổi cơ sở dữ liệu bị lỗi

Các tình huống sử dụng

  • Thêm điểm cắt vào tất cả các phương thức Controller
  • Trong phương thức chú thích @Before, chuyển đổi nguồn dữ liệu động theo tiêu đề được mang trong yêu cầu http
  • Sử dụng mybatis hoặc jpa để thực hiện các thao tác

Gặp phải một vấn đề

Khi chú thích @Transaction được thêm vào phương thức Controller, việc chuyển đổi động các nguồn dữ liệu sẽ trở nên không hợp lệ vì protected abstract Object determineCurrentLookupKey(); đã được chạy trước mỗi phương thức được chú thích @Before và phương thức này là chìa khóa để chuyển đổi các nguồn dữ liệu.

gỡ rối

Trên thực tế, đây không phải là giải pháp. Chỉ cần không thêm chú thích giao dịch vào phương thức Controller. Nếu bạn phải thêm giao dịch, đừng lưu lớp Service ở giữa.

@Các tình huống và nguyên tắc thất bại giao dịch

1. Phương pháp được sửa đổi với @Transactional

Đối với các phương thức không công khai, @Transactional sẽ được triển khai.

Nguyên nhân gây ra lỗi là do @Transactional được triển khai dựa trên proxy động, một phương thức không công khai và thông tin đối tượng proxy động của @Transactional trống nên không thể khôi phục lại.

2. Không có phương thức @Transactional nào được thêm vào bên trong lớp

Khi phương thức @Transactional được gọi, nó sẽ không quay lại khi bạn gọi nó.

Mã kiểm tra như sau.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Dịch vụ
công cộng lớp học Dịch vụ người dùng mở rộng BaseServiceImpl thực hiện Dịch vụ người dùng {
     @Autowired
     riêng tư Người dùng Mapper người dùng Mapper;
     @Ghi đè
     @Giao dịch
     công cộng vô hiệu chèn Một() {
         Người dùng thực thể người dùng thực thể = mới Thực thể người dùng();
         userEntity.setTên người dùng( "Michael_C_2019" );
         //Chèn vào cơ sở dữ liệu
         userMapper.insertSelective(userEntity);
         // Ném ngoại lệ theo cách thủ công
         ném mới Ngoại lệ IndexOutOfBounds();
     }
     @Ghi đè
     công cộng vô hiệu lưuMột() {
         chèn Một();
     }
}

Nguyên tắc thất bại: @Transactional được triển khai dựa trên các đối tượng proxy động và lệnh gọi phương thức bên trong lớp được triển khai thông qua từ khóa this mà không thông qua đối tượng proxy động, do đó việc khôi phục giao dịch sẽ không thành công.

3. Ngoại lệ được bắt bên trong phương thức @Transactional

Nếu ngoại lệ không được ném lại vào khối catch, giao dịch sẽ không được hoàn lại.

Mã như sau:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Ghi đè
     @Giao dịch
     công cộng vô hiệu chèn Một() {
         thử {
             Người dùng thực thể người dùng thực thể = mới Thực thể người dùng();
             userEntity.setTên người dùng( "Michael_C_2019" );
             //Chèn vào cơ sở dữ liệu
             userMapper.insertSelective(userEntity);
             // Ném ngoại lệ theo cách thủ công
             ném mới Ngoại lệ IndexOutOfBounds();
         } nắm lấy (IndexOutOfBoundsException e) {
             e.printStackTrace();
         }
     }

Do đó, Sổ tay dành cho nhà phát triển Java của Alibaba nêu rõ rằng nếu phát hiện ngoại lệ trong phương thức @Transactional, ngoại lệ đó phải được xử lý thủ công.

Mã như sau:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Ghi đè
    @Giao dịch
    công cộng vô hiệu chèn Một() {
        thử {
            Người dùng thực thể người dùng thực thể = mới Thực thể người dùng();
            userEntity.setTên người dùng( "Michael_C_2019" );
            //Chèn vào cơ sở dữ liệu
            userMapper.insertSelective(userEntity);
            // Ném ngoại lệ theo cách thủ công
            ném mới Ngoại lệ IndexOutOfBounds();
        } nắm lấy (IndexOutOfBoundsException e) {
            e.printStackTrace();
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
        }
    }

Nguyên lý lỗi: Bây giờ chúng ta hãy xem mã nguồn của Spring:

Phương thức invokeWithinTransaction trong lớp TransactionAspectSupport.

?
1
Hỗ trợ Giao dịchAspect
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
hai mươi mốt
hai mươi hai
hai mươi ba
hai mươi bốn
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
@Có thể rỗng
     được bảo vệ Đối tượng invokeWithinTransaction(Phương thức phương thức, @Có thể rỗng Class targetClass, TransactionAspectSupport.InvocationCallback gọi lại) ném Có thể ném {
         TransactionAttributeSource tas = cái này .getTransactionAttributeSource();
         Thuộc tính giao dịch txAttr = tas != vô giá trị ? tas.getTransactionAttribute(phương thức, lớp mục tiêu): vô giá trị ;
         PlatformTransactionManager tm = cái này .determineTransactionManager(txAttr);
         Chuỗi joinpointIdentification = cái này .methodIdentification(phương thức, targetClass, txAttr);
         Kết quả đối tượng;
         nếu như (txAttr != vô giá trị && tm trường hợp của Gọi lạiƯa thíchNền tảngGiao dịchQuản lý) {
             TransactionAspectSupport.ThrowableHolder throwableHolder = mới Giao dịchAspectSupport.ThrowableHolder( vô giá trị );
             thử {
                 kết quả = ((CallbackPreferringPlatformTransactionManager)tm).execute(txAttr, (trạng thái) -> {
                     TransactionAspectSupport.TransactionInfo txInfo = cái này .prepareTransactionInfo(tm, txAttr, joinpointIdentification, trạng thái);
                     Đối tượng var9;
                     thử {
                         Đối tượng var8 = invocation.proceedWithInvocation();
                         trở lại biến8;
                     } nắm lấy (Có thể ném var13) {
                         nếu như (txAttr.rollbackOn(var13)) {
                             nếu như (biến thể13 trường hợp của Ngoại lệ thời gian chạy) {
                                 ném (RuntimeException)var13;
                             }
                             ném mới TransactionAspectSupport.ThrowableHolderException(var13);
                         }
                         throwableHolder.throwable = var13;
                         biến9 = vô giá trị ;
                     } Cuối cùng {
                         cái này .cleanupTransactionInfo(txInfo);
                     }
                     trở lại biến9;
                 });
                 nếu như (throwableHolder.throwable != vô giá trị ) {
                     ném throwableHolder.throwable;
                 } khác {
                     trở lại kết quả;
                 }
             } nắm lấy (TransactionAspectSupport.ThrowableHolderException var19) {
                 ném var19.getCause();
             } nắm lấy (TransactionSystemException var20) {
                 nếu như (throwableHolder.throwable != vô giá trị ) {
                     cái này .logger.lỗi( "Ngoại lệ ứng dụng bị ghi đè bởi ngoại lệ cam kết" , throwableHolder.throwable);
                     var20.initApplicationException(throwableHolder.throwable);
                 }
                 ném biến20;
             } nắm lấy (Có thể ném var21) {
                 nếu như (throwableHolder.throwable != vô giá trị ) {
                     cái này .logger.lỗi( "Ngoại lệ ứng dụng bị ghi đè bởi ngoại lệ cam kết" , throwableHolder.throwable);
                 }
                 ném biến21;
             }
         } khác {
             TransactionAspectSupport.TransactionInfo txInfo = cái này .createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
             kết quả = vô giá trị ;
             thử {
                 kết quả = invocation.proceedWithInvocation();
             } nắm lấy (Có thể ném var17) {
               //Khi xảy ra ngoại lệ, hãy khôi phục giao dịch trong logic catch
                 cái này .completeTransactionAfterThrowing(txInfo, var17);
                 ném biến17;
             } Cuối cùng {
                 cái này .cleanupTransactionInfo(txInfo);
             }
             cái này .commitTransactionAfterReturning(txInfo);
             trở lại kết quả;
         }
     }

Phương pháp này bắt được ngoại lệ và khôi phục giao dịch trong catch, do đó nếu bạn bắt được ngoại lệ trong phương thức của mình và không có ngoại lệ mới nào được đưa vào catch, giao dịch sẽ không được khôi phục.

Trên đây là kinh nghiệm cá nhân của tôi, hy vọng có thể giúp bạn tham khảo và mong bạn có thể ủng hộ tôi.

Liên kết gốc: https://blog.csdn.net/m0_37659871/article/details/81672373.

Cuối cùng, bài viết này về giải quyết vấn đề chuyển đổi động và thay đổi cơ sở dữ liệu không hợp lệ do chú thích @Transaction kết thúc tại đây. Nếu bạn muốn biết thêm về giải quyết vấn đề chuyển đổi động và thay đổi cơ sở dữ liệu không hợp lệ do chú thích @Transaction, vui lòng tìm kiếm các bài viết trên CFSDN hoặc tiếp tục duyệt các bài viết liên quan. Tôi hy vọng bạn sẽ ủng hộ blog của tôi trong tương lai! .

37 4 0
qq735679552
Hồ sơ cá nhân

Tôi là một lập trình viên xuất sắc, rất giỏi!

Nhận phiếu giảm giá Didi Taxi miễn phí
Mã giảm giá Didi Taxi
Giấy chứng nhận ICP Bắc Kinh số 000000
Hợp tác quảng cáo: 1813099741@qq.com 6ren.com