Metode @Transactional memanggil metode lain tanpa anotasi @Transactional?

89

Saya telah melihat metode di kelas Layanan yang ditandai sebagai @Transactional, tetapi itu juga memanggil beberapa metode lain di kelas yang sama yang tidak ditandai sebagai @Transactional.

Apakah ini berarti bahwa panggilan ke metode terpisah menyebabkan aplikasi membuka koneksi terpisah ke DB atau menangguhkan transaksi induk, dll?

Apa perilaku default untuk metode tanpa anotasi apa pun yang dipanggil oleh metode lain dengan @Transactionalanotasi?

goe
sumber

Jawaban:

119

Saat Anda memanggil metode tanpa @Transactionaldalam blok transaksi, transaksi induk akan melanjutkan ke metode baru. Ini akan menggunakan koneksi yang sama dari metode induk (dengan @Transactional) dan pengecualian apa pun yang disebabkan dalam metode yang dipanggil (tanpa @Transactionalakan menyebabkan transaksi dibatalkan seperti yang dikonfigurasi dalam definisi transaksi.

Jika Anda memanggil metode dengan @Transactionalanotasi dari metode dengan @Transactionalinstance yang sama, maka perilaku transaksional metode yang disebut tidak akan berdampak apa pun pada transaksi. Tetapi jika Anda memanggil metode dengan definisi transaksi dari metode lain dengan definisi transaksi, dan mereka berada dalam contoh yang berbeda, maka kode dalam metode yang dipanggil akan mengikuti definisi transaksi yang diberikan dalam metode yang dipanggil.

Anda dapat menemukan detail selengkapnya di bagian Manajemen transaksi deklaratif dari dokumentasi transaksi musim semi .

Model transaksi deklaratif pegas menggunakan proxy AOP. jadi proxy AOP bertanggung jawab atas pembuatan transaksi. Proksi AOP akan aktif hanya jika metode dengan dalam contoh dipanggil dari luar contoh.

Arun P Johny
sumber
apakah itu perilaku default pegas?
goe
Iya. Ini adalah perilaku default.
Arun P Johny
2
@Tomas Ya. Tetapi juga harus disebutkan bahwa mengubah propagasi transaksi pada metode yang dipanggil dari metode @Transactional lain tidak akan berpengaruh.
Fil
1
@Tomasz, Itulah yang saya maksud dengan mengatakan will follow the transaction definitions given in the called method. Tetapi jika panggilan tersebut berasal dari instance objek yang sama, panggilan tersebut tidak akan berpengaruh karena panggilan tersebut tidak akan menyebar melalui proxy aop yang bertanggung jawab untuk pemeliharaan transaksi.
Arun P Johny
5
@Filip, Itu tidak sepenuhnya benar, Jika Anda memanggil metode dengan @Transactionaldefinisi dari objek / instance yang berbeda maka meskipun metode pemanggilan memiliki @Transactionalatribut yang berbeda , metode yang dipanggil akan mengikuti definisi transaksinya sendiri.
Arun P Johny
24
  • Apakah itu berarti panggilan ke metode terpisah menyebabkan aplikasi membuka koneksi terpisah ke DB atau menangguhkan transaksi induk, dll?

Itu tergantung pada tingkat propagasi . Berikut semua kemungkinan nilai level .

Misalnya jika level propagasi NESTED, transaksi saat ini akan "ditangguhkan" dan transaksi baru akan dibuat ( catatan: pembuatan aktual dari transaksi bersarang hanya akan berfungsi pada manajer transaksi tertentu )

  • Apa perilaku default untuk metode tanpa anotasi yang dipanggil oleh metode lain dengan anotasi @Transactional?

Tingkat penyebaran default (yang Anda sebut "perilaku") DIPERLUKAN . Jika metode "dalam" dipanggil yang memiliki @Transactionalanotasi di dalamnya (atau ditransaksikan secara deklaratif melalui XML), metode tersebut akan dijalankan dalam transaksi yang sama , misalnya "tidak ada yang baru" dibuat.

tolitius
sumber
Bagaimana dengan sub-panggilan NOT_SUPPORTED yang tidak memiliki penjelasan apa pun? Apakah itu mewarisi NOT_Supported atau apakah mereka membuka transaksi baru karena DIBUTUHKAN adalah defaultnya? Misalnya: f1.call () {f2 ()} dengan penjelasan TIDAK DIDUKUNG untuk f1 dan non untuk f2.
Dave
8

@Transactional menandai batas transaksi (awal / akhir) tetapi transaksi itu sendiri terikat ke utas. Setelah transaksi dimulai, ia menyebar ke seluruh pemanggilan metode hingga metode asli kembali dan transaksi melakukan / memutar kembali.

Jika metode lain dipanggil yang memiliki anotasi @Transactional, propagasi bergantung pada atribut propagasi dari anotasi tersebut.

sourcedelica.dll
sumber
3 jawaban bertentangan satu sama lain dalam beberapa hal, tidak yakin mana yang lebih akurat.
Trump 2020 - Keadilan akan datang
1
@EricWang Hanya ingin berbagi bahwa saya menguji skenario ini hari ini dan jawaban oleh Arun P Johny (dengan komentar) adalah yang paling akurat untuk skenario pemanggilan internal ini .
Vinay Vissh
3

Metode bagian dalam akan mempengaruhi metode luar jika metode bagian dalam tidak dianotasi dengan @Transactional.

Jika metode bagian dalam juga dianotasi dengan @Transactional dengan REQUIRES_NEW, berikut akan terjadi.

...
@Autowired
private TestDAO testDAO;

@Autowired
private SomeBean someBean;

@Override
@Transactional(propagation=Propagation.REQUIRED)
public void outerMethod(User user) {
  testDAO.insertUser(user);
  try{
    someBean.innerMethod();
  } catch(RuntimeException e){
    // handle exception
  }
}


@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void innerMethod() {
  throw new RuntimeException("Rollback this transaction!");
}

Metode bagian dalam diberi anotasi REQUIRES_NEWdan menampilkan RuntimeException sehingga akan menyetel transaksinya ke rollback tetapi TIDAK AKAN MEMPENGARUHI transaksi luar. Transaksi luar DIJEDA ketika transaksi dalam dimulai dan kemudian dilanjutkan SETELAH transaksi dalam diselesaikan. Mereka berjalan secara independen satu sama lain sehingga transaksi luar DAPAT berhasil dilakukan.

saran3h
sumber
1
Untuk memperjelas bagi pemula, saya cukup yakin innerMethod () harus berada pada bean yang berbeda (alias Objek java yang dikelola Spring) daripada outerMethod (). Jika keduanya pada kacang yang sama, menurut saya innerMethod tidak akan benar-benar menggunakan perilaku Transaksional yang dideklarasikan dalam penjelasannya. Melainkan akan menggunakan apa yang dideklarasikan di deklarasi outerMethod (). Ini karena cara Spring menangani AOP, yang digunakan untuk anotasi @Transactional ( docs.spring.io/spring/docs/3.0.x/spring-framework-reference/… )
johnsimer