Haruskah Anda menempatkan @Transactional
di DAO
kelas dan / atau metode mereka atau lebih baik untuk membubuhi keterangan kelas Layanan yang memanggil menggunakan objek DAO? Atau masuk akal untuk membubuhi keterangan kedua "lapisan"?
Haruskah Anda menempatkan @Transactional
di DAO
kelas dan / atau metode mereka atau lebih baik untuk membubuhi keterangan kelas Layanan yang memanggil menggunakan objek DAO? Atau masuk akal untuk membubuhi keterangan kedua "lapisan"?
Jawaban:
Saya pikir transaksi milik pada lapisan Layanan. Itu yang tahu tentang unit kerja dan kasus penggunaan. Ini jawaban yang tepat jika Anda memiliki beberapa DAO yang disuntikkan ke dalam Layanan yang perlu bekerja sama dalam satu transaksi.
Secara umum saya setuju dengan yang lain yang menyatakan bahwa transaksi biasanya dimulai pada tingkat layanan (tergantung pada rincian yang Anda butuhkan tentu saja).
Namun, sementara itu saya juga mulai menambahkan @Transactional(propagation = Propagation.MANDATORY)
ke lapisan DAO saya (dan lapisan lain yang tidak diizinkan untuk memulai transaksi tetapi memerlukan yang sudah ada) karena jauh lebih mudah untuk mendeteksi kesalahan di mana Anda lupa memulai transaksi di pemanggil ( misalnya layanan). Jika DAO Anda dijelaskan dengan propagasi wajib Anda akan mendapatkan pengecualian yang menyatakan bahwa tidak ada transaksi aktif ketika metode dipanggil.
Saya juga memiliki tes integrasi di mana saya memeriksa semua kacang (prosesor pos kacang) untuk anotasi ini dan gagal jika ada @Transactional
anotasi dengan propagasi selain Wajib dalam kacang yang bukan milik lapisan layanan. Dengan cara ini saya memastikan kami tidak memulai transaksi pada lapisan yang salah.
@Transactional
kelas implementasi Layanan, dan saya harus memakai implementasi kelas @Transactional(propagation = MANDATORY)
DAO (repositori)?
Anotasi Transaksional harus ditempatkan di sekitar semua operasi yang tidak dapat dipisahkan.
Misalnya, panggilan Anda adalah "ubah kata sandi". Itu terdiri dari dua operasi
Jadi di atas, jika audit gagal, maka haruskah perubahan kata sandi juga gagal? Jika demikian, maka transaksi harus sekitar 1 dan 2 (demikian pada lapisan layanan). Jika email gagal (mungkin harus memiliki beberapa jenis gagal aman sehingga ini tidak akan gagal) maka haruskah mengembalikan perubahan kata sandi dan audit?
Ini adalah jenis pertanyaan yang perlu Anda tanyakan ketika memutuskan di mana harus meletakkan @Transactional
.
Jawaban yang benar untuk arsitektur Spring tradisional adalah menempatkan semantik transaksional pada kelas layanan, untuk alasan yang telah dijelaskan orang lain.
Tren yang muncul di Spring adalah ke arah desain berbasis domain (DDD). Spring Roo mencontohkan tren dengan baik. Idenya adalah untuk membuat objek domain POJO jauh lebih kaya daripada yang ada pada arsitektur Spring khas (biasanya mereka anemia ), dan khususnya untuk menempatkan transaksi dan semantik bertahan pada objek domain itu sendiri. Dalam kasus di mana semua yang diperlukan adalah operasi CRUD sederhana, pengontrol web beroperasi langsung pada objek domain POJO (mereka berfungsi sebagai entitas dalam konteks ini), dan tidak ada tingkat layanan. Dalam kasus di mana ada semacam koordinasi yang diperlukan antara objek domain, Anda dapat memiliki pegangan layanan kacang itu, dengan@Transaction
sesuai tradisi. Anda dapat mengatur propagasi transaksi pada objek domain ke sesuatu seperti REQUIRED
sehingga objek domain menggunakan transaksi yang ada, seperti transaksi yang dimulai pada kacang layanan.
Secara teknis teknik ini memanfaatkan AspectJ dan <context:spring-configured />
. Roo menggunakan definisi antar-tipe AspectJ untuk memisahkan entitas semantik (transaksi dan kegigihan) dari hal-hal objek domain (pada dasarnya bidang dan metode bisnis).
Kasus normal adalah memberi keterangan pada tingkat lapisan layanan, tetapi ini benar-benar tergantung pada kebutuhan Anda.
Membuat anotasi pada lapisan layanan akan menghasilkan transaksi yang lebih lama daripada membuat anotasi pada level DAO. Tergantung pada tingkat isolasi transaksi yang dapat menyebabkan masalah, karena transaksi bersamaan tidak akan melihat perubahan satu sama lain dalam misalnya. BACA ULANG.
Membuat anotasi pada DAO akan membuat transaksi sesingkat mungkin, dengan kelemahan yang memperlihatkan fungsi lapisan layanan Anda tidak akan dilakukan dalam satu transaksi (dapat dikembalikan).
Tidak masuk akal untuk membubuhi keterangan kedua lapisan jika mode propagasi diatur ke default.
Saya meletakkannya @Transactional
di @Service
layer dan mengatur rollbackFor
pengecualian dan readOnly
untuk mengoptimalkan transaksi lebih lanjut.
Secara default @Transactional
hanya akan mencari RuntimeException
(Pengecualian tidak dicentang), dengan mengatur rollback ke Exception.class
(Pengecualian Tercentang) itu akan mengembalikan untuk setiap pengecualian.
@Transactional(readOnly = false, rollbackFor = Exception.class)
Atau masuk akal untuk membubuhi keterangan kedua "lapisan"? - tidak masuk akal untuk membubuhi keterangan lapisan layanan dan lapisan dao - jika seseorang ingin memastikan bahwa metode DAO selalu disebut (diperbanyak) dari lapisan layanan dengan propagasi "wajib" dalam DAO. Ini akan memberikan beberapa batasan untuk metode DAO agar tidak dipanggil dari lapisan UI (atau pengontrol). Juga - ketika unit menguji lapisan DAO khususnya - memiliki catatan DAO juga akan memastikan diuji untuk fungsionalitas transaksional.
propagation=Propagation.REQUIRES_NEW
. Kalau tidak untuk sebagian besar kasus, termasuk propogasi = wajib, DAO hanya akan berpartisipasi dalam transaksi yang sudah ada yang dimulai oleh lapisan layanan.
Juga, Spring merekomendasikan hanya menggunakan anotasi pada kelas beton dan bukan antarmuka.
http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html
Untuk Transaksi di tingkat basis data
sebagian besar saya gunakan @Transactional
di DAO hanya pada level metode, jadi konfigurasi dapat secara khusus untuk metode / menggunakan default (diperlukan)
Metode DAO yang mendapatkan pengambilan data (pilih ..) - tidak perlu
@Transactional
ini dapat menyebabkan beberapa overhead karena pencegat transaksi / dan proxy AOP yang perlu dieksekusi juga.
Metode DAO yang melakukan insert / update akan mendapatkan @Transactional
blog yang sangat bagus di transkripsional
Untuk tingkat aplikasi -
Saya menggunakan transaksional untuk logika bisnis, saya ingin dapat mengembalikan jika terjadi kesalahan tak terduga
@Transactional(rollbackFor={MyApplicationException.class})
public void myMethod(){
try {
//service logic here
} catch(Throwable e) {
log.error(e)
throw new MyApplicationException(..);
}
}
Transactional
inJava
Biasanya, seseorang harus melakukan transaksi pada lapisan layanan.
Tetapi seperti yang dinyatakan sebelumnya, atomicity dari operasi adalah apa yang memberi tahu kita di mana anotasi diperlukan. Jadi, jika Anda menggunakan kerangka kerja seperti Hibernate, di mana satu operasi "simpan / perbarui / hapus / modifikasi" pada objek memiliki potensi untuk memodifikasi beberapa baris dalam beberapa tabel (karena kaskade melalui grafik objek), dari Tentu saja harus ada manajemen transaksi pada metode DAO khusus ini.
@Transactional
Anotasi harus ditempatkan di sekitar semua operasi yang tidak dapat dipisahkan. Menggunakan @Transactional
propagasi transaksi ditangani secara otomatis. Dalam hal ini jika metode lain dipanggil dengan metode saat ini, maka metode itu akan memiliki opsi untuk bergabung dengan transaksi yang sedang berlangsung.
Jadi mari kita ambil contoh:
Kami memiliki 2 model yaitu Country
dan City
. Pemetaan Relasional Country
dan City
model seperti seseorang Country
dapat memiliki beberapa Kota sehingga pemetaan seperti,
@OneToMany(fetch = FetchType.LAZY, mappedBy="country")
private Set<City> cities;
Di sini Negara dipetakan ke beberapa kota dengan menjemputnya Lazily
. Jadi, inilah peran @Transactinal
ketika kita mengambil objek Negara dari basis data maka kita akan mendapatkan semua data objek Negara tetapi tidak akan mendapatkan Kumpulan kota karena kita mengambil kota LAZILY
.
//Without @Transactional
public Country getCountry(){
Country country = countryRepository.getCountry();
//After getting Country Object connection between countryRepository and database is Closed
}
Ketika kita ingin mengakses Set of Cities dari objek negara maka kita akan mendapatkan nilai null di Set itu karena objek Set dibuat hanya Set ini tidak menginisialisasi dengan data yang ada untuk mendapatkan nilai dari Set yang kita gunakan @Transactional
yaitu,
//with @Transactional
@Transactional
public Country getCountry(){
Country country = countryRepository.getCountry();
//below when we initialize cities using object country so that directly communicate with database and retrieve all cities from database this happens just because of @Transactinal
Object object = country.getCities().size();
}
Jadi pada dasarnya @Transactional
Layanan dapat melakukan beberapa panggilan dalam satu transaksi tanpa menutup koneksi dengan titik akhir.
@Transactional
sebenarnya
Lebih baik memilikinya di lapisan layanan! Ini jelas dijelaskan pada salah satu artikel yang saya temui kemarin! Inilah tautan yang bisa Anda periksa!
The @Transactional
harus digunakan pada lapisan layanan karena mengandung logika bisnis. Lapisan DAO biasanya hanya memiliki operasi CRUD basis data.
// the service class that we want to make transactional
@Transactional
public class DefaultFooService implements FooService {
Foo getFoo(String fooName);
Foo getFoo(String fooName, String barName);
void insertFoo(Foo foo);
void updateFoo(Foo foo);
}
Spring doc: https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html
Lapisan layanan adalah tempat terbaik untuk menambahkan @Transactional
anotasi karena sebagian besar logika bisnis hadir di sini, ini berisi perilaku kasus penggunaan tingkat detail.
Misalkan kita menambahkannya ke DAO dan dari layanan kita memanggil 2 kelas DAO, satu gagal dan sukses lainnya, dalam hal ini jika @Transactional
tidak pada layanan satu DB akan melakukan dan lainnya akan rollback.
Karenanya rekomendasi saya adalah gunakan anotasi ini dengan bijak dan gunakan hanya pada lapisan Layanan.
Pertama-tama mari kita tentukan di mana kita harus menggunakan transaksi ?
Saya pikir jawaban yang benar adalah - ketika kita perlu memastikan bahwa urutan tindakan akan diselesaikan bersama sebagai satu operasi atom atau tidak ada perubahan yang akan dilakukan bahkan jika salah satu tindakan gagal.
Ini adalah praktik terkenal untuk memasukkan logika bisnis ke dalam layanan. Jadi metode layanan dapat berisi tindakan berbeda yang harus dilakukan sebagai unit kerja logis tunggal. Jika demikian - maka metode tersebut harus ditandai sebagai Transaksional . Tentu saja, tidak setiap metode memerlukan batasan seperti itu, jadi Anda tidak perlu menandai seluruh layanan sebagai transaksional .
Dan bahkan lebih - jangan lupa untuk mempertimbangkan bahwa @Transactional jelas, dapat mengurangi kinerja metode. Untuk melihat seluruh gambar Anda harus mengetahui tingkat isolasi transaksi. Mengetahui hal itu dapat membantu Anda menghindari penggunaan @Transaksional di tempat yang belum tentu diperlukan.
Lebih baik menyimpan @Transaksional di lapisan tengah yang terpisah antara DAO dan Lapisan Layanan. Karena, rollback sangat penting, Anda dapat menempatkan semua manipulasi DB di lapisan tengah dan menulis logika bisnis di Service Layer. Lapisan tengah akan berinteraksi dengan lapisan DAO Anda.
Ini akan membantu Anda dalam banyak situasi seperti ObjectOptimisticLockingFailureException - Pengecualian ini terjadi hanya setelah Transaksi Anda selesai. Jadi, Anda tidak dapat menangkapnya di lapisan tengah tetapi Anda dapat menangkapnya di lapisan layanan Anda sekarang. Ini tidak akan mungkin terjadi jika Anda memiliki @Transactional di lapisan Layanan. Meskipun Anda dapat menangkap Controller tetapi Kontroler harus sebersih mungkin.
Jika Anda mengirim surat atau sms di utas terpisah setelah menyelesaikan semua opsi simpan, hapus, dan perbarui, Anda dapat melakukan ini dalam layanan setelah Transaksi selesai di lapisan tengah Anda. Sekali lagi, jika Anda menyebut @Transactional di lapisan layanan, email Anda akan masuk walaupun transaksi Anda gagal.
Jadi memiliki layer @Transaction tengah akan membantu membuat kode Anda lebih baik dan mudah ditangani. Jika tidak, Jika Anda menggunakan lapisan DAO, Anda mungkin tidak dapat mengembalikan semua operasi. Jika Anda menggunakan lapisan Layanan, Anda mungkin harus menggunakan AOP (Pemrograman Berorientasi Aspek) dalam kasus-kasus tertentu.
Idealnya, lapisan Layanan (Manajer) mewakili logika bisnis Anda dan karenanya harus dijelaskan dengan. @Transactional
Lapisan layanan dapat memanggil DAO yang berbeda untuk melakukan operasi DB. Mari kita asumsikan situasi di mana Anda memiliki sejumlah operasi DAO dalam metode layanan. Jika operasi DAO 1 Anda gagal, orang lain mungkin masih lulus dan Anda akan berakhir dengan kondisi DB yang tidak konsisten. Lapisan Layanan Annotating dapat menyelamatkan Anda dari situasi seperti itu.
Saya lebih suka menggunakan @Transactional
lapisan layanan di tingkat metode.