Spring事务管理 -- Spring快速入门保姆级教程(五)(2)

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: Spring事务管理 -- Spring快速入门保姆级教程(五)

4.Spring事务角色

  1. Spring事务角色分为事务管理员和事务协调员
  • 事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法
  • 事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法
  1. 结合入门案例分析

  • 在入门案例中,没加@Transactional注解开启事务的情况下,减钱的outmoney方法、加钱的方法inmoney以及transfer接口都会各自开启一个事务,各自独立。当运行加钱事务出现异常的时候,减钱操作并不会加入加钱操作的事务回滚中,导致整个业务运行失败。
  • 当只用@Transactional注解开启事务后,事务减钱事务TI与加钱事务T2都加入事务T,成为一个事务,这样当事务中的加钱事务部分出现问题时,整个事务回滚,程序终止运行,整体业务正常运行成功。

5.spring事务属性–rollbackfor

  1. 属性简介
属性 作用 示例
readonly 设置是否为只读事务 readOnly=true 只读事务
timeout 设置事务超时时间 timeout=-1(永不超时)
rollbackfor 设置事务回滚异常(class) {NullPointException.class rollbackFor=
rollbackForClassName 设置事务回滚异常(string) 同上格式为字符串
noRollbackFor 设置事务不回滚异常(class) noRollbackFor= (NullPointException.class}
noRollbackForClassName 设置事务不回滚异常(string) 同上格式为字符串
propagation 设置事务传播行为
  1. 添加事务属性格式举例
public interface AccountService {
    /**
     * 转账操作
     * @param out 传出方
     * @param in 转入方
     * @param money 金额
     */
    //配置当前接口方法具有事务
    @Transactional(readOnly = true,timeout = -1)
    public void transfer(String out,String in ,Double money) ;
}
  1. rollbackfor属性介绍
  • 在业务层实现类中抛出一个IOException异常
@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
    public void transfer(String out,String in ,Double money) throws IOException {
        accountDao.outMoney(out,money);
        //模拟抛出IOException异常
        if(true){throw new IOException();}
        accountDao.inMoney(in,money);
    }
}
  • 运行模拟测试类

  • 观察数据库表我们发现,开启事务后在遇到抛IOException类型的异常时,事务不会主动回滚,导致整体业务失败,这时候需要主动去配置。
public interface AccountService {
    /**
     * 转账操作
     * @param out 传出方
     * @param in 转入方
     * @param money 金额
     */
    //配置当前接口方法具有事务
    @Transactional(rollbackFor = {IOException.class})
    public void transfer(String out,String in ,Double money) throws IOException;
}

此时再次运行模拟测试类,当检测到IOExctpition类型的异常时,事务T回滚,数据库表中的数据不变。

  • 开启Spring事务只回滚两种事务:ERROR系列(如内存溢出) 和 运行时异常(如NO Point Exception)。其余的均需要通过rollbackfor属性手动配置。

6.入门案例进阶–转账业务追加日志

  1. 案例需求及实现思路

  1. 编码环境准备
  • 创建数据库表tbl_log

sql建表语句

use spring_db;
drop table if exists tbl_log;
create table tbl_log(
  id int primary key auto_increment,
  info varchar(100),
  createDate varchar(20)
);
INSERT INTO tbl_log VALUES (1, '转账操作由Tom到Jerry,金额:100.0', '20:55:49');

表格示例

  • LogDao数据层接口
public interface LogDao {
    @Insert("insert into tbl_log (info,createDate) values(#{info},now())")
    void log(String info);
}
  • LogService 业务层接口
public interface LogService {
    @Transactional
    void log(String out, String in, Double money);
}
  • LogService 业务层接口实现类
@Service
public class LogServiceImpl implements LogService {
    @Autowired
    private LogDao logDao;
    public void log(String out,String in,Double money ) {
        logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
    }
}
  • 将IOException相关的代码注释掉,保留最基础的Spring事务代码
  • 文件结构示例

  1. 用try…finally结构编写业务层实现类AccountServiceImpl并运行测试类
@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;
    @Autowired
    private LogService logService;
    public void transfer(String out,String in ,Double money) {
        try{
            accountDao.outMoney(out,money);
            int i = 1/0;
            accountDao.inMoney(in,money);
        }finally {
            logService.log(out,in,money);
        }
    }
}
  • 将数据库中的金额分别手动修改重置到1000,并执行测试类

7. Spring事务属性–事务传播行为

  1. 探讨添加了异常后,日志能否正常加载

  • 运行结果分析

此时再次运行测试类,我们可以发现数据库表中金额表数值由于开启了事务,当出现异常时,事务回滚,金额数值不变。同时日志表的数据也没有发生变化,不符合我们的预期。

  • 存在的问题:

日志的记录与转账操作隶属同一个事务,同成功同失败

  • 实现效果预期改进:

无论转账操作是否成功,日志必须保留,这时就需要通过事务传播行为来解决这个问题

  1. spring事务的7种传播行为
required (默认传播行为),如果当前有事务,其他就用当前事务,不会新增事务。例如:方法A调用方法B,它们用同一个事务。(如果B没有事务,它们会用同一个事务。)(只要有一个回滚,整体就会回滚)
requires_new 如果当前有事务,其他不会加入当前事务,会新增事务。即他们的事务没有关系,不是同一个事务。如果其他没有事务,那么以当前事务运行。例如:方法A调用方法B,它们用不同的事务。(B不会用A的事务,会新增事务)
supports 当前没有事务,就以非事务运行。当前有事务呢?就以当前事务运行。例如:方法A调用方法B,如果A没有事务,那么B就以非事务运行。如果A有事务就以A事务为准。如果A没有事务,那么B就会以非事务执行。
mandatory 其他没有事务就会抛异常。当前没有事务抛出异常,当前有事务则支持当前事务。支持当前事务,如果当前没有事务就会抛出异常。例如:方法A调用方法B,如果方法A没有事务,那么就会抛出异常。
not_supported 以非事务执行。例如:方法A调用方法B,方法B会挂起事务A以非事务方式执行。
never 以非事务执行,如果存在事务,抛出异常。总是以非事务执行,如果存在事务,那么就抛出异常。
nested 如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与Required一样。例如:方法A中调用了方法B,B中try catch手动回滚,A不会回滚。
  1. 设置日志接口方法的事务传播行为属性
public interface LogService {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    void log(String out, String in, Double money);
}
  1. 运行测试类观察效果

基于以上结果,Spring事务传播行为设置成功,业务功能运行正常。

`博客内容借鉴了bilibili黑马程序员SSM课程资料,如有侵权,请联系作者删除`

总结

欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下。


相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
3月前
|
监控 Java API
Spring Boot 3.2 结合 Spring Cloud 微服务架构实操指南 现代分布式应用系统构建实战教程
Spring Boot 3.2 + Spring Cloud 2023.0 微服务架构实践摘要 本文基于Spring Boot 3.2.5和Spring Cloud 2023.0.1最新稳定版本,演示现代微服务架构的构建过程。主要内容包括: 技术栈选择:采用Spring Cloud Netflix Eureka 4.1.0作为服务注册中心,Resilience4j 2.1.0替代Hystrix实现熔断机制,配合OpenFeign和Gateway等组件。 核心实操步骤: 搭建Eureka注册中心服务 构建商品
625 3
|
30天前
|
监控 Java 数据库连接
《深入理解Spring》事务管理——数据一致性的守护者
Spring事务管理确保数据一致性,支持声明式与编程式两种方式。通过@Transactional注解简化配置,提供传播行为、隔离级别、回滚规则等灵活控制,结合ACID特性保障业务逻辑可靠执行。
|
2月前
|
缓存 Java 应用服务中间件
Spring Boot配置优化:Tomcat+数据库+缓存+日志,全场景教程
本文详解Spring Boot十大核心配置优化技巧,涵盖Tomcat连接池、数据库连接池、Jackson时区、日志管理、缓存策略、异步线程池等关键配置,结合代码示例与通俗解释,助你轻松掌握高并发场景下的性能调优方法,适用于实际项目落地。
490 5
|
4月前
|
Java Linux 网络安全
Linux云端服务器上部署Spring Boot应用的教程。
此流程涉及Linux命令行操作、系统服务管理及网络安全知识,需要管理员权限以进行配置和服务管理。务必在一个测试环境中验证所有步骤,确保一切配置正确无误后,再将应用部署到生产环境中。也可以使用如Ansible、Chef等配置管理工具来自动化部署过程,提升效率和可靠性。
492 13
|
5月前
|
安全 Java 数据库
Spring Boot 框架深入学习示例教程详解
本教程深入讲解Spring Boot框架,先介绍其基础概念与优势,如自动配置、独立运行等。通过搭建项目、配置数据库等步骤展示技术方案,并结合RESTful API开发实例帮助学习。内容涵盖环境搭建、核心组件应用(Spring MVC、Spring Data JPA、Spring Security)及示例项目——在线书店系统,助你掌握Spring Boot开发全流程。代码资源可从[链接](https://pan.quark.cn/s/14fcf913bae6)获取。
663 2
|
存储 SQL Java
Spring事务管理的底层逻辑—源码解析
首先进入CglibAopProxy.class的intercept方法打上一个Debug断点调试,或者在JdkDynamicAopProxy.class的invoke方法(如果目标方法是继承接口方式实现),根据不同实现方法类型选择不同的动态代理类
239 0
Spring事务管理的底层逻辑—源码解析
|
XML Java 数据格式
【spring源码学习】spring的事务管理的源码解析
【一】spring事务管理(1)spring的事务管理,是基于aop动态代理实现的。对目标对象生成代理对象,加入事务管理的核心拦截器==>org.springframework.transaction.interceptor.TransactionInterceptor。
2160 0
|
4月前
|
Java Spring 容器
SpringBoot自动配置的原理是什么?
Spring Boot自动配置核心在于@EnableAutoConfiguration注解,它通过@Import导入配置选择器,加载META-INF/spring.factories中定义的自动配置类。这些类根据@Conditional系列注解判断是否生效。但Spring Boot 3.0后已弃用spring.factories,改用新格式的.imports文件进行配置。
843 0