Penelitian utama dalam artikel ini adalah perambatan transaksi musim semi dan prinsip -prinsip implementasinya, yang diperkenalkan sebagai berikut.
Spring saat ini merupakan standar de facto untuk pengembangan Java, berkat kenyamanannya, fungsi lengkap, dan mudah digunakan. Selama proses pengembangan, pengoperasian DB adalah operasi yang sangat umum, dan ketika datang ke DB, itu melibatkan transaksi. Selama proses pengembangan transaksi yang normal, bahkan jika Anda tidak menyadarinya, tidak akan ada efek samping pada pelaksanaan normal program. Namun, jika pengecualian terjadi dan transaksi tidak ditangani dengan benar, hasil yang tidak terduga dapat terjadi. Musim semi telah merangkum berbagai operasi dalam hal transaksi, terutama munculnya transaksi deklaratif, membuat pengembangan lebih nyaman. Spring memperluas transaksi dan mendukung definisi atribut propagasi berganda, yang juga merupakan fokus dari artikel ini.
Tidak secara ketat, transaksi adalah singkatan dari berbagai operasi. Operasi ini berlaku atau tidak ada yang berlaku (setara dengan tidak dieksekusi). Proses operasi umum disederhanakan sebagai berikut:
coba {koneksi conn = getConnection (); // Lakukan beberapa operasi basis data} catch (Exception e) {conn.rollback ();} akhirnya {conn.close ();}Beberapa masalah dapat dilihat dari kode di atas:
Spring memberikan transaksi deklaratif, jadi kami tidak perlu memperhatikan implementasi spesifik dari lapisan yang mendasarinya, dan memblokir berbagai detail implementasi dari lapisan yang mendasarinya. Untuk mendukung kontrol transaksi yang baik oleh beberapa bisnis yang kompleks, Spring memberikan atribut propagasi transaksi, dan dikombinasikan dengan transaksi deklaratif, itu telah menjadi alat transaksi utama.
Di kelas TransactionDefinition, Spring menyediakan 6 properti propagasi, yang dijelaskan dengan contoh sederhana.
Pengingat hangat: Berikut ini disebutkan dengan transaksi saat ini mengacu pada penggunaan koneksi yang sama di bagian bawah, tetapi objek keadaan transaksi dapat diciptakan kembali dan tidak memengaruhinya. Artikel tersebut menyebutkan bahwa hanya ada satu transaksi saat ini, yang berarti bahwa koneksi yang mendasarinya dibagikan, dan tidak peduli tentang berapa banyak objek keadaan transaksi (transactionstatus) yang dibuat.
Deskripsi: Jika transaksi sudah ada, maka bergabunglah dengan transaksi. Jika tidak ada transaksi, buat transaksi. Ini adalah nilai atribut propagasi default.
Mari kita lihat contoh kecil, kodenya adalah sebagai berikut:
@Transactionalpublic void service () {servicea (); serviceB ();}@TransactionalServicea ();@TransactionserviceB ();Servicea dan serviceB keduanya menyatakan transaksi. Secara default, propagasi = propagation_required. Selama seluruh proses panggilan layanan, hanya ada satu transaksi bersama. Ketika pengecualian terjadi, semua operasi akan digulung kembali.
Deskripsi: Jika suatu transaksi sudah ada, bergabunglah dengan transaksi, jika tidak, transaksi kosong yang disebut dibuat (dapat dianggap bukan eksekusi transaksi).
Mari kita lihat contoh kecil, kodenya adalah sebagai berikut:
layanan public void () {servicea (); Lempar runtimeException baru ();}@transaksional (propagasi = propagasi.supports) servicea ();Saat ini tidak ada transaksi ketika Servicea sedang dieksekusi, sehingga pengecualian yang dilemparkan dalam layanan tidak akan menyebabkan Serviceea mundur.
Mari kita lihat contoh kecil lain, kodenya adalah sebagai berikut:
layanan public void () {servicea ();}@transactional (propagation = propagation.supports) servicea () {do sql 1 1/0; lakukan sql 2}Karena ServiceA tidak memiliki transaksi saat berjalan, pada saat ini, jika sumber data yang mendasarinya defaultAutocommit = true, maka SQL1 efektif. Jika defaultAutocommit = false, maka SQL1 tidak valid. Jika layanan memiliki tag @transactional, Servicea membagikan transaksi layanan (tidak lagi bergantung pada DefaultAutocommit). Pada saat ini, Servicea semuanya digulung kembali.
Deskripsi: Transaksi saat ini harus ada, jika tidak, pengecualian akan dilemparkan.
Mari kita lihat contoh kecil, kodenya adalah sebagai berikut:
public void service () {serviceB (); servicea ();} serviceB () {do sql} @transactional (propagation = propagation.mandatory) servicea () {do sql}Dalam hal ini, layanan pelaksanaan akan melempar pengecualian. Jika defaultAutocommit = true, serviceB tidak akan kembali. Jika defaultAutOcommit = false, eksekusi serviceB akan tidak valid.
Catatan: Jika suatu transaksi saat ini ada, pertama-tama merangkum konten terkait transaksi saat ini menjadi suatu entitas, kemudian menciptakan kembali transaksi baru, menerima entitas ini sebagai parameter, dan menggunakannya untuk pemulihan transaksi. Pernyataan yang lebih tumpul adalah menangguhkan transaksi saat ini (tidak diperlukan transaksi) dan membuat transaksi baru. Dalam hal ini, tidak ada ketergantungan antara kedua transaksi, dan transaksi baru dapat digulung kembali, tetapi transaksi eksternal terus dieksekusi.
Mari kita lihat contoh kecil, kodenya adalah sebagai berikut:
@Transactionalpublic void service () {serviceB (); coba {servicea (); } catch (Exception e) {}} serviceB () {do sql} @transactional (propagation = propagation.requires_new) servicea () {do sql 1 1/0; lakukan sql 2}Saat memanggil antarmuka layanan, karena servicea menggunakan kebutuhan_new, itu akan membuat transaksi baru. Namun, karena Servicea melempar pengecualian runtime, Servicea digulung kembali. Dalam metode layanan, pengecualian ditangkap, sehingga serviceB diajukan secara normal. Perhatikan bahwa Coba ... Tangkap Kode dalam Layanan diperlukan, jika tidak layanan akan melempar pengecualian, menyebabkan LayananB digulung kembali.
Catatan: Jika suatu transaksi saat ini ada, menangguhkan transaksi saat ini, dan kemudian metode baru dieksekusi di lingkungan tanpa transaksi dan di lingkungan tanpa transaksi musim semi, komit SQL sepenuhnya tergantung pada nilai properti DefaultAutocomitmit.
Mari kita lihat contoh kecil, kodenya adalah sebagai berikut:
@Transactionalpublic void service () {serviceB (); servicea ();} serviceB () {do sql} @transactional (propagation = propagation.not_supported) servicea () {do sql 1 1/0; lakukan sql 2}Ketika metode layanan dipanggil, pengecualian dilemparkan ketika kode 1/0 dalam metode Servicea dijalankan. Karena ServiceA berada dalam lingkungan bebas transaksi, apakah SQL1 efektif tergantung pada nilai defaultAutocommit. Ketika defaultAutocommit = true, SQL1 efektif, tetapi serviceB akan digulung kembali karena layanan melempar pengecualian.
Deskripsi: Jika transaksi saat ini ada, pengecualian dilemparkan, jika tidak kode dieksekusi pada lingkungan tanpa transaksi.
Mari kita lihat contoh kecil, kodenya adalah sebagai berikut:
public void service () {serviceB (); servicea ();} serviceB () {do sql} @transactional (propagation = propagation.never) servicea () {do sql 1 1/0; lakukan sql 2}Setelah contoh di atas panggilan layanan, jika defaultAutOcommit = true, metode serviceB dan sql1 di servicea akan berlaku.
Catatan: Jika ada transaksi saat ini, gunakan teknologi savepoint untuk menyimpan keadaan transaksi saat ini, dan kemudian lapisan yang mendasarinya berbagi koneksi. Ketika kesalahan terjadi dalam bersarang, ia akan kembali ke status savepoint dengan sendirinya. Selama pengecualian ditangkap oleh luar, ia dapat terus melakukan transaksi eksternal tanpa terganggu oleh bisnis yang tertanam. Namun, jika pengecualian dilemparkan oleh transaksi eksternal, seluruh transaksi besar akan digulung kembali.
Catatan: Manajer Transaksi Konfigurasi Musim Semi harus secara aktif menentukan NestedTransactionAllowed = true, seperti yang ditunjukkan di bawah ini:
<bean id = "DataTransActionManager"> <properti name = "DataSource" ref = "datadataSource" /> <name properti = "sulransactionAllowed" value = "true" /> < /bean>
Lihat contoh kecil, kodenya adalah sebagai berikut:
@Transactionalpublic void service () {servicea (); coba {serviceB (); } catch (exception e) {}} servicea () {do sql} @transactional (propagation = propagation.nested) serviceB () {do sql1 1/0; lakukan sql2}ServiceB adalah layanan tertanam, dan pengecualian runtime dilemparkan secara internal, sehingga ServiceB digulung kembali. Karena layanan menangkap pengecualian, Servicea dapat mengirimkannya secara normal.
Mari kita lihat contoh lain, kodenya adalah sebagai berikut:
@Transactionalpublic void service () {servicea (); serviceB (); 1/0;}@transaksional (propagasi = propagation.nested) servicea () {do sql} serviceB () {do sql}Karena layanan melempar pengecualian, seluruh metode layanan akan digulung kembali. (Ini berbeda dari propagation_requires_new. Layanan tertanam di bawah mode bersarang akan digulung kembali dengan pengecualian dari transaksi eksternal.)
Contoh -contoh di atas menggambarkan beberapa atribut propagasi yang disediakan oleh transaksi musim semi digunakan untuk memenuhi berbagai kebutuhan bisnis yang berbeda, yang dapat ditentukan oleh bisnis. Selanjutnya, mari kita lihat apa ketergantungan teknis paling penting dari Spring mengimplementasikan atribut propagasi ini. Bagian ini mencantumkan propagation_requires_new dan propagasi. Dibutuhkan untuk deskripsi singkat masing -masing.
Panggilan kode berikut:
@Transactionalpublic void service () {serviceB (); coba {servicea (); } catch (Exception e) {}}@transactional (propagation = propagation.requires_new) servicea () {do sql 1 1/0; do sql 2} serviceB () {do sql}Skema eksekusi adalah sebagai berikut:
A. Buat objek status transaksi, dapatkan koneksi baru, setel ulang autocommit, fetchsize, timeout dan properti lain dari koneksi
B. Mengikat koneksi ke variabel threadlocal
C. Menunda transaksi saat ini, merangkum objek keadaan transaksi saat ini, koneksi dan informasi lainnya ke dalam objek sumber daya yang ditangguhkan, yang dapat digunakan untuk pemulihan
D. Buat objek status transaksi baru, perolehkan kembali koneksi baru, atur ulang autocommit, fetchsize, timeout dan properti lain dari koneksi baru. Pada saat yang sama, simpan objek Sumber Sumber Ditangguhkan untuk pemulihan transaksi, dan ikat koneksi baru ke variabel threadlocal (Operasi Overwrite)
e. Tangkap pengecualian, putar kembali koneksi di threadlocal, kembalikan parameter koneksi, tutup koneksi, dan kembalikan sumber daya yang ditangguhkan
F. Kirimkan koneksi dalam variabel threadlocal (menyebabkan layananb diserahkan), mengembalikan parameter koneksi, tutup koneksi, dan mengembalikan koneksi ke sumber data
Jadi hasil eksekusi program adalah bahwa servicea digulung kembali dan layananB berhasil diserahkan.
Panggilan kode berikut:
@Transactionalpublic void service () {servicea (); coba {serviceB (); } catch (exception e) {}} servicea () {do sql} @transactional (propagation = propagation.nested) serviceB () {do sql1 1/0; lakukan sql2}Skema eksekusi adalah sebagai berikut:
A. Buat objek status transaksi, dapatkan koneksi baru, setel ulang autocommit, fetchsize, timeout dan properti lain dari koneksi
B. Mengikat koneksi ke variabel threadlocal
C. Tandai penggunaan objek status transaksi saat ini, dapatkan objek koneksi threadlocal, simpan savePoint dari koneksi saat ini, dan digunakan untuk pemulihan pengecualian. Saat ini, savePoint adalah status setelah servicea dieksekusi
D. Tangkap pengecualian dan gunakan savePoint di C untuk rollback transaksi, yaitu memutar kembali negara ke negara setelah mengeksekusi servicea. Semua eksekusi metode serviceB tidak berlaku
e. Dapatkan Objek Koneksi di Threadlocal, Kirim Transaksi, Pulihkan Properti Koneksi, Tutup Koneksi
Berdasarkan sumber data yang mendasarinya, Spring menggunakan Threadlocal, SavePoint dan poin teknis lainnya untuk mewujudkan berbagai atribut propagasi transaksi, yang memfasilitasi implementasi berbagai layanan kompleks. Hanya dengan memahami prinsip atribut propagasi kita dapat mengontrol transaksi pegas yang lebih baik. Transaksi Spring Rollback bergantung pada penangkapan pengecualian. Secara default, transaksi hanya akan digulung kembali jika runtimeException dan kesalahan dilemparkan. Tentu saja, itu dapat dikonfigurasi. Untuk informasi lebih lanjut, Anda dapat memeriksa anotasi @transactional.
Transaksi deklaratif Spring memberi kita kenyamanan yang luar biasa. Untuk memanfaatkan senjata ini dengan baik, masih perlu untuk memahami prinsip -prinsip yang mendasarinya. Artikel ini hanyalah puncak gunung es transaksi musim semi. Pembaca dapat mengeksplorasi secara mendalam atas dasar ini.
Di atas adalah semua isi artikel ini tentang perambatan transaksi musim semi dan prinsip -prinsip implementasinya. Saya harap ini akan membantu semua orang. Teman yang tertarik dapat terus merujuk ke topik terkait lainnya di situs ini. Jika ada kekurangan, silakan tinggalkan pesan untuk menunjukkannya. Terima kasih teman atas dukungan Anda untuk situs ini!