springboot開啓聲明式事務方式
- 在Application啓動類中加入註解@EnableTransactionManagement(mode = AdviceMode.PROXY)
- 在須要加入事務的方法上加入註解@Transactional
- @Transactional(rollbackFor = RollbackException.class) 拋出指定異常時回滾
/** * <p> * (rollbackFor = RollbackException.class) 拋出自定義異常時,回滾事務。 * </p> * @throws RollbackException */ @Override @Transactional(rollbackFor = RollbackException.class) public void insertThenRollback() throws RollbackException { jdbcTemplate.execute("INSERT INTO Student (NAME) VALUES ('Tom')"); throw new RollbackException(); }
常見問題
例若有這個實現類StudentServiceImpl:html
@Component public class StudentServiceImpl implements StudentService { /** * <p> * (rollbackFor = RollbackException.class) 拋出自定義異常時,回滾事務。 * </p> * @throws RollbackException */ @Override @Transactional(rollbackFor = RollbackException.class) public void insertThenRollback() throws RollbackException { jdbcTemplate.execute("INSERT INTO Student (NAME) VALUES ('BBB')"); throw new RollbackException(); } /** * <p> * spring的事務是經過aop進行代理加強的。 * 這裏是在類的內部直接執行方法調用,並無調用代理類來進行方法調用,因此這裏事務不會回滾。 * </p> * * @throws RollbackException */ @Override public void invokeInsertThenRollback1() throws RollbackException { insertThenRollback(); } }
上面的insertThenRollback()回回滾事務,invokeInsertThenRollback1()調用了insertThenRollback()方法可是不會回滾事務,這是爲何呢? 這是由於spring的事務是經過aop進行代理加強的,但這裏是在類的內部直接執行方法調用,並無調用代理類來進行方法調用,因此這裏事務不會回滾。java
解決辦法
- 第一種方法:經過AopContext.currentProxy()獲取當前類的代理對象。
/** * * 經過AopContext.currentProxy()獲取當前類的代理對象 * * @throws RollbackException */ @Override public void invokeInsertThenRollback2() throws RollbackException { ((StudentService) (AopContext.currentProxy())).insertThenRollback(); }
- 第二種方法:把本身的實例注入進來,讓spring爲咱們建立代理。
//把本身的實例注入進來 @Autowired private StudentService studentService; /** * 把本身的實例注入進來 * @throws RollbackException */ @Override public void invokeInsertThenRollback3() throws RollbackException { studentService.insertThenRollback(); }
原文出處:https://www.cnblogs.com/monkjavaer/p/11461946.htmlspring