Sebelum menjelaskan masalahnya, izinkan saya menjelaskan beberapa premis. Asumsikan bahwa transaksi database dikonfigurasi dalam file konfigurasi Spring dengan cara berikut:
<bean id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:transaction-manager="transactionManager" yang didorong oleh anotasi />
Sekarang ada UserDao dan SecurityService:
@Repositori public class UserDao { public User getUser() { // query pengguna dari tabel pengguna return queryObject("pilih * dari pesanan pengguna berdasarkan id desc limit 1" } }
@Layanan @Layanan Keamanan kelas publik Transaksional { @Autowired private UserDao userDao; public void checkUserInfo() { while(true) { Pengguna pengguna = userDao.getUser(); ()) { System.out.println("Tom ada di sini");
Selama proses pemanggilan metode SecurityService#checkUserInfo(), data yang diperoleh melalui metode userDao#getUser() tetap tidak berubah meskipun data baru bernama Tom dimasukkan saat ini, loop tidak akan berakhir. Selain itu, menghapus anotasi @Transactional di SecurityService tidak akan membantu.
Pertama-tama, saya pikir mungkin ada masalah dengan kumpulan koneksi database. Hal yang sama juga berlaku ketika digantikan oleh milik Spring sendiri. Kemudian saya memanggil objek Connection langsung dari JdbcTemplate dan menggunakan metode JDBC asli untuk mengoperasikan database Saat ini, data berubah secara real time, jadi saya pikir transaksi Spring seharusnya terikat pada thread operasi saat ini. Setelah memeriksa kode sumber, saya menemukan dalam metode DataSourceUtils#doGetConnection bahwa Spring membuat Koneksi pada setiap DataSource dari setiap utas dan mengikatnya ke transaksi. Karena file konfigurasi tx:annotation-driven melakukan pengikatan transaksi pada semua lapisan Layanan (kelas yang dianotasi dengan @Service), Koneksi yang sama diikat di thread yang sama terlepas dari apakah @Transactional digunakan, tetapi tidak dilakukan hanya operasi bisnis .
Setelah banyak percobaan dan mencari informasi, akhirnya saya menemukan solusi yang tepat: cukup tambahkan anotasi @Transactional(propagation = Propagation.NOT_SUPPORTED) ke metode checkUserInfo di atas. Tentu saja, Anda juga dapat memperoleh Koneksi dan melakukan operasi secara manual, atau Anda dapat menggunakan paket DateUtils untuk melakukan operasi.