学习内容:
使用 java Spring 框架 开发时使用的 事务
- @Transactional 注解
- 使用 TransactionTemplate 工具类
学习笔记:
事务管理对于软件开发来说是至关重要的,即使出现异常情况,它也可以保证数据的一致性。
spring 支持 编程式事务 和 声明式事务 两种方式。
编程式事务管理基于底层的API,使用 TransactionTemplate 或者直接使用底层的 PlatformTransactionManager、TransactionDefinition 等核心接口,开发者完全可以通过编程的方式来进行事务管理。编程式事务方式需要是开发者在代码中手动的管理事务的开启、提交、回滚等操作。其中 Spring 推荐使用 TransactionTemplate 工具类。
Boolean execute = transactionTemplate.execute(e -> {
inspectOrderItemService.updateById(item);
int orderCount = inspectOrderItemService.count(new QueryWrapper<InspectOrderItemEntity>().eq("order_id", orderItemEntity.getOrderId()).eq("status", 1).eq("deleted_flag", "N"));
order.setCount(orderCount);
if(orderCount == orderEntity.getDeviceCount()){
order.setStatus(1);//保存
}else{
order.setStatus(0);//关单
}
inspectService.updateById(order);
return Boolean.TRUE;
});
声明式事务管理 方法允许开发者配置的帮助下来管理事务,而不需要依赖底层API进行硬编码。开发者可以只使用注解或基于配置的 XML 来管理事务。相对于 编程式事务来说较优 ,是spring提倡的非侵入式的开发方式。使用@Transactional 注解 即可给方法增加事务控制。
/**
* 保存
*/
@RequestMapping("/save")
@RequiresPermissions("sys:dept:save")
@Transactional
public R save(@RequestBody SysDeptEntity dept){
if(StringUtils.isEmpty(dept.getDeptId())){
dept.setState(EntityState.NEW);
}else{
dept.setState(EntityState.MODIFIED);
}
sysDeptService.save(dept);
return R.ok();
}
声明式事务管理的优点:
1、声明式事务帮助我们节省了很多代码,它会自动帮我们进行事务的开启、提交以及回滚等操作。
2、声明式事务管理使用了 AOP 实现的,本质就是在目标方法执行前后进行拦截。在目标方法执行前加入或创建一个事务,在执行方法执行后,根据实际情况选择提交或是回滚事务。
3、使用声明式事务管理,对代码没有侵入性,方法内只需要写业务逻辑就可以了。
声明式事务管理的缺点:
声明式事务也具有相应的缺点,即:声明式事务的粒度问题。
1、声明式事务有一个局限,那就是它的最小粒度要作用在方法上。如果想要给一部分代码块增加事务的话,那就需要把这个部分代码块单独独立出来作为一个方法。
总结:
1、@Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional也不会报错,但方法没有事务功能。
2、@Transactional 注解应该只被应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。
3、用 spring 事务管理器,由spring来负责数据库的打开,提交,回滚。默认遇到运行期特例(throw new RuntimeException(“注释”);)会回滚,即遇到不受检查(unchecked)的特例时回滚;而遇到需要捕获的特例(throw new Exception(“注释”);)不会回滚,即遇到受检查的特例(就是非运行时抛出的异常,编译器会检查到的异常叫受检查例外或说受检查异常)时,需我们指定方式来让事务回滚要想所有异常都回滚,要加上 @Transactional( rollbackFor={Exception.class,其它异常}) .如果遇到 unchecked特例 时不回滚,需: @Transactional(notRollbackFor=RunTimeException.class)
4、@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。然而,仅仅 出现@Transactional 注解的不足于开启事务行为,因为它仅仅 是一种元数据,能够被可以识别 @Transactional 注解和上述的配置适当的具有事务行为的beans所使用。
5、使用 @Transactional 注解时 要在具体的类(或类的方法)上使用 ,而不要使用在类所要实现的任何接口上。当然可以在接口上使用 @Transactional 注解,但是这将只能当我们设置了基于接口的代理时它才生效。
5、注解是不能继承的。如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。
事务的使用很重要,需要加强对事务的深入学习!