spring多執行緒中事務處理
阿新 • • 發佈:2018-12-29
什麼是事務:參考連結:https://blog.csdn.net/sinat_33536912/article/details/51200630
專案中遇到的問題:
在加有事務的類中啟用執行緒,執行緒不會重新開啟新的事務而是與當前類共用事務。事務的提交也是一起進行。
程式碼:
import com.transaction.dao.UserDao; import com.transaction.handler.ThreadHandler; import com.transaction.pojo.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Date; @Service @Transactional public class TestService { @Autowired private UserDao userDao; @Autowired private ThreadHandler threadHandler; public void testTransaction (){ try{ User user=new User(); user.setUserphone("18255556666"); user.setUsername("孔空空"); user.setCreateDate(new Date()); userDao.insert(user); threadHandler.testHandler(); System.out.println("執行緒執行完畢"); }catch (Exception e){ e.printStackTrace(); System.out.println("testService 異常"); } } //查詢使用者方法,多執行緒下呼叫 public void selectUser (){ System.out.println("查詢開始"); User user=userDao.selectUser("孔空空"); System.out.println(user.getId()); } } //多執行緒下查詢使用者資料 @Service("threadHandler") public class ThreadHandler { public static Log logger = LogFactory.getLog(ThreadHandler.class); @Autowired private Executor taskAsyncPool; @Autowired private TestService testService; public void testHandler() { taskAsyncPool.execute(new Runnable() { @Override public void run() { logger.info("測試多執行緒事務任務啟動"); try { testService.selectUser(); Thread.sleep(1200000); System.out.println("testHandler執行緒執行完畢"); }catch(Exception e) { e.printStackTrace(); logger.info("系統異常===="+e); } } }); } }
執行結果:丟擲空指標異常。。。。。。。
原因:
testTransaction方法中呼叫執行緒去查詢user表中的資料,線上程中讓執行緒等待,保證testTransaction中的插入執行完畢,但是執行緒中呼叫查詢方法時發現user表中並沒有剛剛插入的資料,也就是testTransaction的事務沒有提交,因為執行緒還沒有執行完畢。通過這個實驗發現,新開啟的執行緒並沒有開啟新的事務,而是跟service中的方法公用同一個事務,這才導致查詢方法中出現空指標異常的情況。
解決方法:在多執行緒的方法上加註解
@Transactional(propagation = Propagation.REQUIRES_NEW)
@Transactional(propagation = Propagation.REQUIRES_NEW)在多執行緒的方法或類上加上該註解,那麼執行緒就會新開啟一個事務,與service中的事務沒有關係。service中方法執行完畢之後就提交它的事務,多執行緒的事務自己管理。
程式碼:
@Service("threadHandler") public class ThreadHandler { public static Log logger = LogFactory.getLog(ThreadHandler.class); @Autowired private Executor taskAsyncPool; @Autowired private TestService testService; @Transactional(propagation = Propagation.REQUIRES_NEW) public void testHandler() { taskAsyncPool.execute(new Runnable() { @Override public void run() { logger.info("測試多執行緒事務任務啟動"); try { testService.selectUser(); Thread.sleep(1200000); System.out.println("testHandler執行緒執行完畢"); }catch(Exception e) { e.printStackTrace(); logger.info("系統異常===="+e); } } }); } }
加註解之後的結果:查詢正常並沒有出現空指標的情況
注意:在用該註解時,還發現了個問題,在同一類中使用Propagation.REQUIRES_NEW註解,該註解不作用,只有在不同的類中使用該註解才會重新開啟新的事務。至於為什麼還沒有進行深究。。。。。