Senario terbaru yang dihadapi ialah dalam kaedah A yang dianotasi dengan @Transactional, kaedah B yang ditandakan dengan anotasi @Async telah dipanggil Memandangkan urus niaga kaedah A tidak dilakukan apabila kaedah B dilaksanakan, kaedah B tidak dilakukan Semasa proses pelaksanaan, data yang belum diserahkan dalam kaedah A tidak boleh diperoleh, jadi pada akhirnya, kaedah B dilaksanakan secara tidak normal.
@Transactional public void create(User user){ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 int userId = insert(user); // 更新用户信息 update(userId); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
Seperti kod di atas, saya menandai anotasi transaksi @Transactional pada kaedah mencipta pengguna, dan kemudian memanggil kaedah kemas kini kemas kini() di dalamnya. Kaedah ini ditandakan dengan anotasi @Async. Walaupun kod itu nampaknya tidak mempunyai masalah, apabila kaedah kemas kini() sebenarnya dilaksanakan, kerana ia dilaksanakan oleh utas lain, ada kemungkinan transaksi yang sepadan dengan kaedah create() belum diserahkan lagi, dan kemas kini( ) kaedah tidak dapat membacanya Rekod pengguna yang baru dimasukkan diperoleh, menyebabkan kemas kini gagal.
Laraskan logik untuk memastikan transaksi dilakukan sebelum memanggil kaedah tak segerak
Punca masalah ini adalah disebabkan oleh penggunaan @Transactional dan @Async anotasi bersama-sama, kemudian Kita boleh bermula dari arah ini Mula-mula, kita boleh mengesahkan bahawa transaksi kaedah create() diserahkan, dan kemudian laksanakan kaedah kemas kini tak segerak:
public void create(User user){ int userId = doCreate(user); // 更新用户信息 update(userId); } @Transactional public void doCreate(User user){ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 return insert(user); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
Kaedah tak segerak dipanggil di luar kaedah transaksi, supaya kaedah tak segerak adalah Data transaksi yang komited boleh dibaca.
Kami boleh menggunakan TransactionTemplate untuk menggantikan anotasi @Transactional
@Autowired TransactionTemplate transactionTemplate; public void create(User user){ int userId = transactionTemplate.execute(status->{ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 return insert(user); }); // 更新用户信息 update(userId); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
Dengan menggunakan TransactionTemplate untuk membahagikan butiran transaksi, pastikan transaksi telah dilakukan sebelum memanggil kaedah tak segerak.
Penyelesaian di atas pada asasnya boleh menyelesaikan masalah berikut adalah penyelesaian yang diberikan oleh spring yang terdapat di Internet:
@Transactional public void create(User user){ // 如果用户已存在,则先删除 delete(user.id); // 创建用户 int userId = insert(user); TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { @Override public void afterCommit() { // 更新用户信息 update(userId); } }); } @Async public void update(Integer userId){ Icon icon = getUserIcon(userId); // 更新用户图片 updateUserPohot(userId,icon); }
Dengan mendaftarkan kaedah tak segerak sebagai operasi selepas penyerahan transaksi, Spring It boleh. secara automatik membantu kami melaksanakan operasi yang sepadan selepas transaksi diserahkan.
Atas ialah kandungan terperinci Bagaimana untuk menyelesaikan masalah menggunakan SpringBoot secara tidak segerak dengan transaksi. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!