我个人有一个学习习惯就是把学过的内容整理出来一份重点笔记,笔记往往只会包括我认为比较重要的部分或者容易忘记的部分,以便于我快速复习,如果有错误欢迎大家批评指正。
另外:本篇笔记参考了JavaWeb这个专栏的文章,相当于是这个专栏的压缩版,特此鸣谢作者「_Matthew」
版权声明:本文为CSDN博主「_Matthew」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_46225503/article/details/131730131
事务是一组操作的集合,它是一个不可分割的工作单位。事务会把所有的操作作为一个整体,一起向数据库提交或撤销操作请求。这组操作要么同时发生,要么同时失败。
事务的操作主要又三步:
1、开启事务(一组操作开始前,开启事务):start transaction / begin;
2、提交事务(这组操作全部成功后,提交事务):commit
3、回滚事务(中间任何一个操作出现异常,回滚事务):rollback;
spring框架当中把事务控制的代码已经封装好了,不需要我们手动实现。我们使用了spring框架,我们只需要通过注解@Transactional
就可以完成
@Transactional
作用:就是我们在当前这个方法执行开始之前来开启事务,方法执行完毕之后提交事务。如果在这个方法执行的过程中出现了异常,就会进行事务的回滚。
@Transactional
注解:我们一般会在业务层当中来控制事务,因为业务层当中,一个业务功能可能会包含多个数据访问的操作。在业务层来控制事务,我们就可以将多个数据访问操作控制在一个事务范围内。
接下来,我们就可以在业务方法delete上加上@Transactional
来控制事务。这样的话,如果成功删除部门之后,中间出现错误,导致没有正确执行删除部门下的员工的时候,就会回滚事务,也不会出现只删除了部门而没删除部门下员工的情况。
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Autowired
private EmpMapper empMapper;
@Override
@Transactional //当前方法添加了事务管理
public void delete(Integer id){
//根据部门id删除部门信息
deptMapper.deleteById(id);
//模拟:异常发生
int i = 1/0;
//删除部门下的所有员工信息
empMapper.deleteByDeptId(id);
}
}
默认情况下,只有出现RuntimeException(运行时异常)才会回滚事务。
假如我们想让所有的异常都回滚,需要配置@Transacyion注解当中的rollbackFor属性,通过rollbackFor这个属性可以指定出现何种异常类型回滚事务@Transaction(rollbackFor=Exception.class)
@Slf4j
@Service
public class DeptServiceImpl implements DeptService {
@Autowired
private DeptMapper deptMapper;
@Autowired
private EmpMapper empMapper;
@Override
@Transactional(rollbackFor=Exception.class)
public void delete(Integer id){
//根据部门id删除部门信息
deptMapper.deleteById(id);
//模拟:异常发生
int num = id/0;
//删除部门下的所有员工信息
empMapper.deleteByDeptId(id);
}
}
@Transaction
注解当中的第二个属性propagation,这个属性是用来配置事务的传播行为的
例如:两个事务方法,一个A方法,一个B方法。在这两个方法上都添加了@Transaction注解,就代表这两个方法都具有事务,而在A方法中调用了B方法
所谓的事务传播行为就是指在A方法运行的时候会开启一个事务,在A方法当中又调用了B方法,B方法自身也具有事务,那么在B方法运行的时候,到底是加入到A方法的事务当中来,还是B方法在运行的时候创建一个新的事务呢?这就涉及到事务的传播行为
想要控制事务的传播行为,就在@Transaction注解的后面指定一个属性propagation,通过propagation属性来指定传播行为。下面是一些常见的事务传播行为
AOP(Aspect Oriented Programming)面向切面编程
比如:我们需要统计当前这个项目涨每一个业务方法的执行耗时,如果在每一个方法前后都加上开始时间和结束时间然后相减求得执行时间的话,就会很繁琐。所以我们可以利用AOP,就可以在程序运行期间不修改源代码的基础上对已有方法进行增强
下面讲一个简单的案例:
步骤:
1、导入依赖:在pom.xml中导入AOP的依赖
2、编写AOP程序:针对于特定方法根据业务需要进行编程
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
AOP程序:TimeAspect,下面的程序是为了实现统计各个方法的执行时间
@Component //IOC容器管理
@Aspect //当前类为切面类AOP类
@Slf4j //Log
public class TimeAspect {
@Around("execution(* com.itheima.service.*.*(..))")
public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {
//记录方法执行开始时间
long begin = System.currentTimeMillis();
//执行原始方法
Object result = pjp.proceed();
//记录方法执行结束时间
long end = System.currentTimeMillis();
//计算方法执行耗时
log.info(pjp.getSignature()+"执行耗时: {}毫秒",end-begin);
return result;
}
}
AOP面向切面编程的一些优势:代码无侵入、减少了重复代码、提高开发效率、维护方便
AOP也是一块重要的部分,这里没法很简单的讲明白AOP,所以大家自行找一些比较好的博客看一下