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