Spring事务 @Transactional详解
- 思考:在一些很重要的地方,例如银行存钱的时候,假如你的钱已经进入了Atm中但是,后面你查询余额的时候发现,你的钱并没有存进去。假如你给某人转账,你的账户显示转账成功,但是对方并没有收到钱,这种重要的操作就应该考虑使用事务操作。
事务管理方式
编程式事务管理
使用TransactionTemplate
或者使用底层的PlatformTransactionManager
声明式事务管理
声明式事务建立在AOP之上,对方法前后进行拦截,然后方法开始之前创建或者加入一个事务,在执行完目标方法后更具执行情况提交或者回滚事务。声明式事务一种基于tx和aop的xml配置文件,另一种是基于@Transactional注解。
@Transactional注解使用说明
- 当作用于类上时候,该类的所用Public方法都将具有该类型的事务属性。
- 方法加上
@Transactional(rollbackFor=Exception.class)
肯定会回滚。 - 如果
@Transactional
不加属性那么事务只有在遇到RuntimeException
的时候才会回滚。
@Transactional回滚Or不回滚
try catch捕获异常
- 在执行的过程中,异常被捕获了所以,无法进行回滚。
@RequestMapping("/test1")
@Transactional(rollbackFor = Exception.class)
public String test1() {
try {
Menu menu = new Menu();
menu.setName("事务测试2");
menu.setFlavor("事务测试2");
menu.setPrice((double) 34);
menu.setCount(23);
menu.setId(2);
menuRepository.update(menu);
int a=10/0;
return "sucess";
} catch (Exception e) {
e.printStackTrace();
return "fail";
}
}
- 要想在try catch中也能回滚操作,只需要在catch中加上如下的语句。此时不管有没有异常都会进行回滚操作。
@RequestMapping("/test1")
@Transactional(rollbackFor = Exception.class)
public String test1() {
try {
menuRepository.update(menu);
int a=10/0;
return "sucess";
} catch (Exception e) {
e.printStackTrace();
//只要抛异常则回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
return "fail";
}
}
不捕获异常
- @Transaction加上roolbackfor参数,会进行回滚操作。
@RequestMapping("/test2")
@ApiOperation(value = "事务回滚测试2", notes = "不捕获异常不抛出异常")
@Transactional(rollbackFor = Exception.class)
public String test2() {
menuRepository.update(menu);
int a = 10 / 0;
return "sucess";
}
- 抛出RuntimeException,事务进行回滚
@RequestMapping("/test3")
@ApiOperation(value = "事务回滚测试3", notes = "不加参数")
@Transactional
public String test3() {
menuRepository.update(menu);
int a = 10 / 0;
throw new RuntimeException();
}
- 抛出其他异常事务不回滚
@RequestMapping("/test3")
@Transactional
public String test4() {
menuRepository.update(menu);
int a = 10 / 0;
throw new ArithmeticException();
}
SpringBoot 手动和自动管理事务
手动
@Api("事务手动提交测试")
@RestController
@RequestMapping("/thing")
public class TransactionsController {
@Autowired
MenuRepository menuRepository;
@Autowired
DataSourceTransactionManager dataSourceTransactionManager;
@Autowired
TransactionDefinition transactionDefinition;
@RequestMapping("/test1")
@ApiOperation(value = "事务回滚测试1", notes = "加上Transactional的属性")
public String test1() {
TransactionStatus transactionStatus = null;
try {
//手动开启事务
transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
Menu menu = new Menu();
menu.setName("事务测试2");
menu.setFlavor("事务测试2");
menu.setPrice((double) 34);
menu.setCount(23);
menu.setId(2);
menuRepository.update(menu);
//手动提交事务
dataSourceTransactionManager.commit(transactionStatus);
int a = 10 / 0;
return "sucess";
} catch (Exception e) {
if (transactionStatus != null) {
//手动回滚
dataSourceTransactionManager.rollback(transactionStatus);
}
e.printStackTrace();
return "fail";
}
}
}
自动
见上面的@Transactional的用法