事务的作用
保证数据的一致性原则 遵循acid
事务的分类
编程事务 (手动挡)
1、获取当前项目中的事务管理器
DataSourceTransactionManager
2、可以采取事务管理实现提交、回滚事务操作
举例
添加工具类
package com.jn.exam.eduservice.utils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
/**
* @author 江南大学1033190417
* @date 2022/2/2 22:20
*/
@Component
public class TransactionUtils {
@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
/**
* 开启事务
* @return
*/
public TransactionStatus begin(){
TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute());
return transaction;
}
/**
* 提交事务
* @param transaction
*/
public void commit(TransactionStatus transaction){
dataSourceTransactionManager.commit(transaction);
}
/**
* 回滚事务
* @param transaction
*/
public void rollback(TransactionStatus transaction){
dataSourceTransactionManager.rollback(transaction);
}
}
使用
@PostMapping("test")
@SuppressWarnings("all")//消除所有警告
public R test(Integer num){
TransactionStatus begin = null;
try {
begin= transactionUtils.begin();//开启事务
Student student=new Student();
student.setName("测试");
student.setNumber("1033190415");
student.setPassword(MD5Util.getMD5("123456"));
boolean save = studentService.save(student);
int a=10/num;
if (save) {
transactionUtils.commit(begin);//提交
return R.ok().message("添加成功");
}
}catch (Exception e){
e.printStackTrace();
transactionUtils.rollback(begin);//回滚
return R.error().message("添加失败");
}
return R.error().message("添加失败");
}
缺点:
代码重复,冗余
优点:
很好的扩展性
声明事务 (自动挡)
说明:声明事务实际上就是基于编程事务实现封装
只需要在方法上添加注解@Transactional
注意:@Transactional失效问题:不要try业务逻辑
为什么:如果try,Aop不会补货该异常,就不会回滚
如果非要try可以手动回滚
try {
Student student=new Student();
student.setName("测试");
student.setNumber("1033190415");
student.setPassword(MD5Util.getMD5("123456"));
boolean save = studentService.save(student);
if (save) {
return R.ok().message("添加成功");
}
int a=10/num;
}catch (Exception e){
e.printStackTrace();
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();//手动回滚
return R.error().message("添加失败");
}
开始自定义注解
先自己建一个注解
package com.jn.exam.eduservice.utils;
import java.lang.annotation.*;
/**
* @author 江南大学1033190417
* @date 2022/2/2 22:45
*/
@Target({ElementType.METHOD,ElementType.TYPE})//注解可以用到类和方法上
@Retention(RetentionPolicy.RUNTIME)//生效时刻
@Inherited//说明子类可以继承父类中的该注解
@Documented//添加到注释文档
public @interface MyTransactional {
}
定义一个Aop拦截方法或类上是否有@MyTransactional注解
package com.jn.exam.eduservice.utils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
/**
* 定义一个Aop拦截方法或类上是否有@MyTransactional注解
*
* @author 江南大学1033190417
* @date 2022/2/2 22:51
*/
@Component
@Slf4j
@Aspect
public class ExTransactionAop {
@Autowired
private TransactionUtils transactionUtils;
//环绕通知
@Around(value = "@annotation(com.jn.exam.eduservice.utils.MyTransactional)")
public Object around(ProceedingJoinPoint joinPoint){
TransactionStatus begin=null;
try {
log.info("开启事务");
begin = transactionUtils.begin();
Object proceed = joinPoint.proceed();//目标方法执行
log.info("提交事务");
transactionUtils.commit(begin);
return proceed;
} catch (Throwable e) {
e.printStackTrace();
log.error("回滚事务");
transactionUtils.rollback(begin);
return "系统错误";
}
}
}