Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Putar kembali A jika B salah. boot musim semi, jdbctemplate

@Transactional anotasi di pegas bekerja dengan membungkus objek Anda dalam proxy yang pada gilirannya membungkus metode yang dianotasi dengan @Transactional dalam sebuah transaksi. Karena itu anotasi tidak akan berfungsi pada metode pribadi (seperti pada contoh Anda) karena metode pribadi tidak dapat diwariskan => mereka tidak dapat dibungkus (ini tidak benar jika Anda menggunakan transaksi deklaratif dengan aspekj, maka peringatan terkait proxy di bawah ini tidak berlaku).

Berikut adalah penjelasan dasar tentang cara @Transactional keajaiban musim semi bekerja.

Anda menulis:

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

Tapi inilah yang sebenarnya Anda dapatkan saat menyuntikkan kacang:

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
       }
   }
} 

Ini memiliki keterbatasan. Mereka tidak bekerja dengan @PostConstruct metode karena mereka dipanggil sebelum objek diproksi. Dan bahkan jika Anda mengonfigurasi semuanya dengan benar, transaksi hanya dibatalkan pada tidak dicentang pengecualian secara default. Gunakan @Transactional(rollbackFor={CustomCheckedException.class}) jika Anda perlu rollback pada beberapa pengecualian yang diperiksa.

Peringatan lain yang sering ditemui yang saya tahu:

@Transactional metode hanya akan berfungsi jika Anda menyebutnya "dari luar", dalam contoh berikut b() tidak akan dibungkus dalam transaksi:

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

   @Transactional
   public void b() {
   }
}

Itu juga karena @Transactional bekerja dengan mem-proxy objek Anda. Pada contoh di atas a() akan memanggil X.b() bukan metode "proksi musim semi" yang disempurnakan b() jadi tidak akan ada transaksi. Sebagai solusinya, Anda harus memanggil b() dari kacang lain.

Saat Anda mengalami salah satu peringatan ini dan tidak dapat menggunakan solusi yang disarankan (jadikan metode non-pribadi atau panggil b() dari kacang lain) Anda dapat menggunakan TransactionTemplate alih-alih transaksi deklaratif:

public class A {
    @Autowired
    TransactionTemplate transactionTemplate;

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

...
} 

Perbarui

Menjawab pertanyaan OP yang diperbarui menggunakan info di atas.

Metode mana yang harus dijelaskan dengan @Transactional:changes()? databaseChanges()?

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

Pastikan changes() disebut "dari luar" kacang, bukan dari kelas itu sendiri dan setelah konteks dipakai (mis. ini bukan afterPropertiesSet() atau @PostConstruct metode beranotasi). Pahami bahwa transaksi spring rollback hanya untuk pengecualian yang tidak dicentang secara default (coba lebih spesifik dalam daftar pengecualian rollbackFor yang dicentang).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Apa yang dapat menyebabkan ROWID Oracle berubah?

  2. apakah ada fungsi PRODUCT seperti ada fungsi SUM di Oracle SQL?

  3. Pengumpulan koneksi ODP.NET:Bagaimana cara mengetahui apakah koneksi telah digunakan

  4. Permintaan untuk menemukan pemindaian tabel lengkap di Oracle

  5. Oracle sql:perbarui jika ada yang lain masukkan