Artikel ini akan melakukan penelitian mendalam tentang manajemen transaksi Spring. Terutama memperkenalkan cara kerja @transactional di bagian bawah. Artikel berikut akan memperkenalkan:
Penggunaan atribut seperti propagasi (perambatan transaksi) dan isolasi (isolasi)
Apa jebakan penggunaan transaksi dan bagaimana menghindarinya
JPA dan manajemen transaksi
Penting bahwa JPA itu sendiri tidak menyediakan segala jenis manajemen transaksi deklaratif. Jika Anda menggunakan JPA di luar wadah injeksi ketergantungan, transaksi harus diimplementasikan secara terprogram oleh pengembang.
UserTransaction utx = EntityManager.GetTransAction (); coba {utx.begin (); BusinessLogic (); utx.Commit ();} catch (Exception ex) {utx.rollback (); throwex;}Cara manajemen transaksi ini memungkinkan ruang lingkup transaksi untuk diungkapkan dengan jelas dalam kode, tetapi memiliki kelemahan berikut:
Kode dan kesalahan berulang rentan
Kesalahan apa pun mungkin memiliki dampak yang lebih besar
Kesalahan sulit untuk debug dan direproduksi
Mengurangi keterbacaan basis kode
Bagaimana jika metode ini memanggil metode transaksi lain?
Menggunakan Spring @transactional
Menggunakan Spring @Transactional, kode di atas disederhanakan untuk:
@Transactional publicvoid BusinessLogic () {... Gunakan Entity Manager di dalam transaksi ...}Kode ini lebih ringkas dan dapat dibaca, dan juga merupakan cara yang disarankan untuk berurusan di musim semi saat ini.
Banyak aspek penting seperti perambatan transaksi dapat ditangani secara otomatis dengan menggunakan @transactional. Dalam hal ini, jika BusinessLogic () memanggil metode transaksi lain, metode ini akan menentukan cara bergabung dengan transaksi yang berjalan berdasarkan opsi.
Salah satu kelemahan potensial dari mekanisme yang kuat ini adalah bahwa ia menyembunyikan operasi yang mendasarinya dan sulit untuk debug ketika tidak berfungsi dengan baik.
@Transactional makna
Salah satu poin utama tentang @transactional adalah untuk mempertimbangkan dua konsep terpisah, yang keduanya memiliki ruang lingkup dan siklus hidup mereka sendiri:
konteks kegigihan (konteks kegigihan)
transaksi basis data
@Transactional sendiri mendefinisikan ruang lingkup transaksi tunggal. Transaksi ini berada dalam ruang lingkup konteks kegigihan.
Konteks kegigihan dalam JPA adalah EntityManager, dan implementasi internal menggunakan sesi Hibernate (menggunakan Hibernate sebagai penyedia kegigihan).
Konteks kegigihan hanyalah objek sinkron yang mencatat keadaan objek Java dari koleksi yang terbatas dan memastikan bahwa perubahan pada objek ini pada akhirnya tetap ada pada database.
Ini adalah konsep yang sangat berbeda dari satu transaksi. Manajer entitas dapat digunakan di berbagai transaksi, dan memang digunakan dengan cara ini.
Kapan EntityManager mencakup beberapa transaksi?
Situasi yang paling umum adalah ketika aplikasi menggunakan sesi terbuka dalam mode tampilan untuk menangani pengecualian inisialisasi malas. Artikel sebelumnya telah memperkenalkan kelebihan dan kekurangan dari pendekatan ini.
Dalam hal ini, beberapa kueri yang dijalankan oleh lapisan tampilan berada dalam transaksi terpisah, daripada logika bisnis transaksi tunggal, tetapi kueri ini dikelola oleh manajer entitas yang sama.
Skenario lain adalah bahwa pengembang menandai konteks kegigihan sebagai persistenceContextType.Extended, yang berarti dapat menanggapi banyak permintaan.
Bagaimana cara mendefinisikan hubungan antara EntityManager dan transaksi?
Ini dipilih oleh pengembang aplikasi, tetapi cara yang paling umum untuk JPA Entity Manager adalah mode "Manajer Entitas per Transaksi Aplikasi". Metode Umum Injeksi Manajer Entitas adalah:
@PersistenceContext PrivateEntityManager EM;
Standarnya adalah mode "Manajer Entitas per Transaksi". Dalam mode ini, jika manajer entitas digunakan di dalam metode @transactional, metode ini akan berjalan dalam satu transaksi.
Bagaimana cara kerja @PersistenceContext?
Pertanyaan berikut adalah bagaimana @PersistenceContext hanya dapat menyuntikkan Entity Manager hanya ketika wadah dimulai, dengan asumsi bahwa siklus hidup Entity Manager pendek dan membutuhkan banyak manajer entitas per permintaan.
Jawabannya adalah tidak dapat: EntityManager adalah antarmuka, dan apa yang disuntikkan ke dalam kacang musim semi bukanlah manajer entitas itu sendiri, tetapi proksi sadar konteks (proxy sadar konteks) dari manajer entitas tertentu dalam runtime.
Kelas spesifik yang biasa digunakan untuk proxy adalah ShareDEntityManagerInvocationHandler, yang dapat dikonfirmasi dengan bantuan debugger.
Jadi bagaimana cara kerja @transactional?
Proksi konteks persisten yang mengimplementasikan antarmuka EntityManager bukan satu -satunya bagian dari manajemen transaksi deklaratif, tetapi sebenarnya berisi tiga komponen:
EntityManager Proxy itu sendiri
Bagian transaksi
Manajer Transaksi
Lihatlah ketiga bagian ini dan interaksinya.
Bagian transaksi
Bagian transaksi adalah bagian "sekitar" yang dapat dipanggil sebelum dan sesudah metode bisnis beranotasi. Kelas spesifik yang mengimplementasikan bagian ini adalah TransactionInterceptor.
Ada dua tanggung jawab utama di bagian transaksi:
Dalam 'Sebelum', bagian ini memberikan titik panggilan untuk memutuskan apakah metode bisnis yang dipanggil harus berjalan dalam ruang lingkup transaksi yang sedang berlangsung atau memulai transaksi independen baru.
Di 'After', bagian perlu menentukan bahwa transaksi dilakukan, digulung kembali atau terus berjalan.
Dalam 'Sebelum', bagian transaksi itu sendiri tidak mengandung logika keputusan apa pun, dan keputusan untuk memulai transaksi baru didelegasikan ke manajer transaksi untuk diselesaikan.
Manajer Transaksi
Manajer transaksi perlu menyelesaikan dua masalah berikut:
Haruskah manajer entitas baru dibuat?
Haruskah transaksi baru dimulai?
Ini membutuhkan bagian transaksi untuk ditentukan ketika logika 'sebelum' dipanggil. Keputusan manajer transaksi didasarkan pada dua poin berikut:
Apakah transaksi berlangsung
Properti propagasi dari metode transaksi (misalnya, membutuhkan_new selalu memulai transaksi baru)
Jika Transaction Manager menentukan bahwa Anda ingin membuat transaksi baru, itu akan:
1. Buat manajer entitas baru
2. Manajer Intitas terikat pada utas saat ini
3. Dapatkan koneksi dari kumpulan koneksi database
4. Bind koneksi ke utas saat ini
Gunakan variabel threadlocal untuk mengikat manajer entitas dan koneksi database ke utas saat ini.
Transaksi berjalan ketika mereka disimpan di utas, dan ketika mereka tidak lagi digunakan, manajer transaksi memutuskan apakah akan membersihkannya.
Bagian mana pun dari program dapat diambil dari utas jika diperlukan manajer entitas saat ini dan koneksi database.
EntityManager Proxy
EntityManager Proxy (sudah diperkenalkan sebelumnya) adalah bagian terakhir dari teka -teki. Ketika metode bisnis memanggil EntityManager.persist (), ini tidak dipanggil langsung oleh Entity Manager.
Sebaliknya, metode bisnis memanggil agen, yang mendapatkan manajer entitas saat ini dari utas. Seperti yang disebutkan sebelumnya, manajer transaksi mengikat manajer entitas ke utas.
Setelah memahami berbagai bagian mekanisme @transactional, mari kita lihat konfigurasi pegas yang umum digunakan yang mengimplementasikannya.
Mengintegrasikan tiga bagian
Bagaimana cara menggabungkan tiga bagian sehingga anotasi transaksi dapat bekerja dengan benar? Pertama -tama tentukan pabrik manajer entitas.
Ini memungkinkan Anda untuk menyuntikkan proxy manajer entitas dengan anotasi konteks kegigihan.
@Configuration PublicClass EntityManagerFactoryConfiguration {@Autowired PrivatedataSource DataSource; @Bean (name = "EntityManagerFactory") publicLocalContainerEntityManagerFactoryBean EMF () {LocalContainerentityManagerBeanBean EMF = ... emf.setDataSource (DataSource); emf.setPackagestoscan (newstring [] {"your.package"}); emf.setjPavendorAdapter (newhibernateJPavendorAdapter ()); returneMf;}}Langkah selanjutnya adalah mengonfigurasi Transaction Manager dan menerapkan aspek transaksi di kelas beranotasi @transactional.
Konfigurasi @EnabletRansactionManagement PublicClass TransactionManAgersConfig {@Autowired EntityManagerFactory emf; @Autowired privatedataSource dataSource; @bean (name = "transactionManager") publicplatformransAmageRanMerager () {jpatransactionager = newjpatransactionManager (); tm.setentityManagerFactory (EMF); tm.setDataSource (DataSource); returnm;}}Annotation @enabletransactionManagement memberi tahu Spring bahwa kelas yang dijelaskan oleh @transactional dikelilingi oleh cut-away transaksi. Dengan cara ini @transactional dapat digunakan.
Meringkaskan
Mekanisme manajemen transaksi deklaratif Spring sangat kuat, tetapi dapat disalahgunakan atau mudah dikonfigurasi.
Ketika masalah seperti mekanisme ini tidak berfungsi dengan baik atau gagal mencapai hasil operasi yang diharapkan, akan sangat membantu untuk memahami cara kerja internalnya.
Hal terpenting yang perlu diingat adalah dengan mempertimbangkan dua konsep: transaksi dan konteks kegigihan, masing -masing dengan siklus hidupnya yang jelas yang tidak dapat dibaca.
Di atas adalah semua isi artikel ini tentang prinsip kerja Spring @transactional. 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!