Transaksi dengan Spring dan JPA

1. Ikhtisar

Tutorial ini akan membahas cara yang benar untuk mengonfigurasi Transaksi Musim Semi , cara menggunakan anotasi @Transactional, dan perangkap umum.

Untuk diskusi yang lebih mendalam tentang konfigurasi persistensi inti, lihat tutorial Musim Semi dengan JPA.

Pada dasarnya, ada dua cara berbeda untuk mengonfigurasi Transaksi - anotasi dan AOP - masing-masing dengan kelebihannya sendiri. Kami akan membahas anotasi-config yang lebih umum di sini.

2. Konfigurasi Transaksi

Semi 3.1 memperkenalkan para @EnableTransactionManagement penjelasan bahwa kita dapat menggunakan dalam @Configuration kelas dan mengaktifkan dukungan transaksional:

@Configuration @EnableTransactionManagement public class PersistenceJPAConfig{ @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(){ //... } @Bean public PlatformTransactionManager transactionManager(){ JpaTransactionManager transactionManager = new JpaTransactionManager(); transactionManager.setEntityManagerFactory( entityManagerFactoryBean().getObject() ); return transactionManager; } }

Namun, jika kita menggunakan proyek Spring Boot, dan memiliki dependensi spring-data- * atau spring-tx di classpath, maka manajemen transaksi akan diaktifkan secara default .

3. Konfigurasi Transaksi Dengan XML

Sebelum 3.1 atau jika Java bukan merupakan pilihan, berikut adalah konfigurasi XML, menggunakan berbasis anotasi dan dukungan namespace:

4. Anotasi @Transactional

Dengan transaksi yang dikonfigurasi, sekarang kita dapat membuat anotasi kacang dengan @Transactional baik di tingkat kelas atau metode:

@Service @Transactional public class FooService { //... }

Anotasi juga mendukung konfigurasi lebih lanjut :

  • yang Propagasi Jenis transaksi
  • yang Isolasi Tingkat transaksi
  • a Timeout untuk operasi yang dibungkus oleh transaksi
  • a readOnly flag - petunjuk bagi penyedia persistensi bahwa transaksi harus hanya baca
  • yang Rollback aturan untuk transaksi

Perhatikan bahwa - secara default, rollback terjadi untuk runtime, hanya pengecualian yang tidak dicentang. Pengecualian yang dicentang tidak memicu rollback transaksi. Kita bisa, tentu saja, mengonfigurasi perilaku ini dengan parameter anotasi rollbackFor dan noRollbackFor .

5. Potensi Jebakan

5.1. Transaksi dan Proksi

Pada level tinggi, Spring membuat proxy untuk semua kelas yang dianotasi dengan @Transactional - baik di kelas atau di salah satu metode. Proksi memungkinkan kerangka kerja untuk memasukkan logika transaksional sebelum dan sesudah metode yang berjalan - terutama untuk memulai dan melakukan transaksi.

Yang penting untuk diingat adalah, jika kacang transaksional mengimplementasikan sebuah antarmuka, secara default proxy-nya adalah Java Dynamic Proxy. Ini berarti bahwa hanya panggilan metode eksternal yang masuk melalui proxy yang akan dicegat. Setiap panggilan pemanggilan mandiri tidak akan memulai transaksi apa pun, meskipun metode tersebut memiliki anotasi @Transactional .

Peringatan lain dalam menggunakan proxy adalah hanya metode publik yang harus dianotasi dengan @Transactional. Metode visibilitas lainnya hanya akan mengabaikan anotasi secara diam-diam karena ini tidak diproksikan.

Artikel ini membahas perangkap proxy lebih lanjut dengan sangat rinci di sini.

5.2. Mengubah Tingkat Isolasi

Kami juga dapat mengubah tingkat isolasi transaksi:

@Transactional(isolation = Isolation.SERIALIZABLE)

Perhatikan bahwa ini sebenarnya telah diperkenalkan di Spring 4.1; jika kita menjalankan contoh di atas sebelum Spring 4.1, itu akan menghasilkan:

org.springframework.transaction.InvalidIsolationLevelException : JPA standar tidak mendukung tingkat isolasi kustom - gunakan JpaDialect khusus untuk implementasi JPA Anda

5.3. Transaksi Hanya-Baca

The dibaca bendera biasanya menimbulkan kebingungan, terutama ketika bekerja dengan JPA; dari Javadoc:

Ini hanya berfungsi sebagai petunjuk untuk subsistem transaksi yang sebenarnya; itu tidak akan selalu menyebabkan kegagalan upaya akses tulis. Manajer transaksi yang tidak dapat menafsirkan petunjuk hanya-baca tidak akan mengeluarkan pengecualian ketika dimintai transaksi hanya-baca.

Faktanya adalah kita tidak dapat memastikan bahwa penyisipan atau pembaruan tidak akan terjadi ketika flag readOnly disetel. Perilaku ini bergantung pada vendor, sedangkan JPA adalah vendor agnostik.

Ini juga penting untuk memahami bahwa yang dibaca bendera hanya relevan di dalam transaksi. Jika operasi terjadi di luar konteks transaksional, panji akan diabaikan begitu saja. Contoh sederhananya akan memanggil metode yang dianotasi dengan:

@Transactional( propagation = Propagation.SUPPORTS,readOnly = true )

dari konteks non-transaksional - transaksi tidak akan dibuat dan flag readOnly akan diabaikan.

5.4. Pencatatan Transaksi

Metode yang berguna untuk memahami masalah terkait transaksional adalah menyempurnakan pencatatan dalam paket transaksional. Paket yang relevan di Spring adalah " org.springframework.transaction", yang harus dikonfigurasi dengan tingkat pencatatan TRACE.

6. Kesimpulan

Kami membahas konfigurasi dasar semantik transaksional menggunakan Java dan XML, cara menggunakan @Transactional, dan praktik terbaik dari Strategi Transaksional.

Seperti biasa, kode yang disajikan dalam artikel ini tersedia di Github.