Oracle
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Oracle

Cuộn lại A nếu B sai. khởi động mùa xuân, jdbctemplate

@Transactional chú thích trong mùa xuân hoạt động bằng cách bao bọc đối tượng của bạn trong một proxy, đến lượt nó sẽ bao bọc các phương thức được chú thích bằng @Transactional trong một giao dịch. Do đó, chú thích sẽ không hoạt động trên các phương thức riêng tư (như trong ví dụ của bạn) vì phương thức riêng tư không thể được kế thừa => chúng không thể được bao bọc (điều này không đúng nếu bạn sử dụng các giao dịch khai báo với khía cạnhj, thì các cảnh báo liên quan đến proxy bên dưới không áp dụng).

Đây là giải thích cơ bản về cách @Transactional tác phẩm phép thuật mùa xuân.

Bạn đã viết:

class A {
    @Transactional
    public void method() {
    }
}

Nhưng đây là những gì bạn thực sự nhận được khi tiêm một hạt đậu:

class ProxiedA extends A {
   private final A a;

   public ProxiedA(A a) {
       this.a = a;
   }

   @Override
   public void method() {
       try {
           // open transaction ...
           a.method();
           // commit transaction
       } catch (RuntimeException e) {
           // rollback transaction
       } catch (Exception e) {
           // commit transaction
       }
   }
} 

Điều này có những hạn chế. Chúng không hoạt động với @PostConstruct bởi vì chúng được gọi trước khi đối tượng được proxied. Và ngay cả khi bạn đã định cấu hình tất cả một cách chính xác, các giao dịch chỉ được khôi phục khi bỏ chọn ngoại lệ theo mặc định. Sử dụng @Transactional(rollbackFor={CustomCheckedException.class}) nếu bạn cần khôi phục trên một số ngoại lệ đã kiểm tra.

Một cảnh báo thường gặp khác mà tôi biết:

@Transactional phương thức sẽ chỉ hoạt động nếu bạn gọi nó là "từ bên ngoài", trong ví dụ sau b() sẽ không được bao bọc trong giao dịch:

class X {
   public void a() {
      b();
   }

   @Transactional
   public void b() {
   }
}

Đó cũng là vì @Transactional hoạt động bằng cách ủy quyền đối tượng của bạn. Trong ví dụ trên a() sẽ gọi X.b() không phải là phương pháp "spring proxy" nâng cao b() vì vậy sẽ không có giao dịch. Để giải quyết vấn đề, bạn phải gọi b() từ một hạt đậu khác.

Khi bạn gặp phải bất kỳ cảnh báo nào trong số này và không thể sử dụng cách giải quyết được đề xuất (đặt phương thức là không riêng tư hoặc gọi b() từ một bean khác) bạn có thể sử dụng TransactionTemplate thay vì các giao dịch khai báo:

public class A {
    @Autowired
    TransactionTemplate transactionTemplate;

    public void method() {
        transactionTemplate.execute(status -> {
            A();
            B();
            return null;
        });
    }

...
} 

Cập nhật

Trả lời câu hỏi được cập nhật OP bằng cách sử dụng thông tin ở trên.

Phương thức nào nên được chú thích với @Transactional:changes ()? databaseChanges ()?

@Transactional(rollbackFor={Exception.class})
public void changes() throws Exception {
    someLogicBefore();
    databaseChanges();
    someLogicAfter();
}

Đảm bảo rằng changes() được gọi là "từ bên ngoài" của bean, không phải từ chính lớp và sau khi ngữ cảnh được khởi tạo (ví dụ:đây không phải là afterPropertiesSet() hoặc @PostConstruct phương pháp chú thích). Hiểu rằng giao dịch Spring rollbacks chỉ dành cho các trường hợp ngoại lệ chưa được kiểm tra theo mặc định (hãy cố gắng cụ thể hơn trong danh sách rollbackF đối với các trường hợp ngoại lệ đã kiểm tra).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hàm FROM_TZ () trong Oracle

  2. Làm thế nào để lấy tên ngày trong tuần từ một ngày?

  3. oracle - Chia nhiều giá trị được phân tách bằng dấu phẩy trong bảng oracle thành nhiều hàng

  4. Bộ sưu tập PL / SQL:Bảng lồng nhau trong cơ sở dữ liệu Oracle

  5. Chèn nhiều hàng với trình tự trong Oracle