首先spring中事务有两种方式:编程事务 、声明事务
编程事务:
获取项目中事务管理器 DataSourceTransactionManager
采用事务管理提交回滚操作
1 |
@Component public class TransactionUtils { @Autowired private DataSourceTransactionManager dataSourceTransactionManager; //获取当前事务 public TransactionStatus begin(){ //采用默认传播行为 TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionAttribute()); return transaction; } //提交 public void commit(TransactionStatus transaction){ dataSourceTransactionManager.commit(transaction); } public void rollback(TransactionStatus transaction){ dataSourceTransactionManager.rollback(transaction); } } |
业务层
1 |
@RestController public class TxServiceImpl { @Autowired private TransactionUtils transactionUtils; //采取事务 @GetMapping("/tx") public String insertUser(User user){ TransactionStatus begin == null; //begin开启事务,若不提交相当于对数据使用行锁 try { begin = transactionUtils.begin(); String res = userMapper.insert(user)>0?"成功":"失败"; int j = 1/user.getUserId(); transactionUtils.commit(begin); return res; }catch (Exception e){ if (begin != null){ transactionUtils.rollback(begin); return "系统错误"; } } } } |
代码重复性强,扩展性好
声明事务:
只需要加入注解 @Transactional
当方法执行完,aop采取拦截,判断成功还是异常采取对应的操作
失效问题:
当方法中用try捕获异常,异常不会抛到aop,则不会回滚,
需要手动回滚在catch中使用
TransactionAspectSupport.currentTransactionStatus().set
RollbackOnly();
自定义注解
创建注解
1 |
//作用范围 @Target({ElementType.METHOD,ElementType.TYPE}) //通过反射机制获取注解 @Retention(RetentionPolicy.RUNTIME) @Inherited //注释文档 @Documented public @interface MyTransactional { } |
定义aop拦截方法
1 |
@Component @Aspect public class ExtTransactionalAop { @Autowired private TransactionUtils transactionUtils; //拦截方法上有自定义注解 走环绕通知 @Around(value = "@annotation(com.lzq.aop.MyTransactional)") public Object around(ProceedingJoinPoint joinPoint){ TransactionStatus begin = null; try { begin = transactionUtils.begin(); //获取目标方法 Object res = joinPoint.proceed(); transactionUtils.commit(begin); return res; } catch (Throwable throwable) { throwable.printStackTrace(); if (begin != null){ transactionUtils.rollback(begin); } return "系统错误"; } } } |
此时将自定义注解加在方法上即可