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课程资料,如有侵权,请联系作者删除`

总结

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


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
2月前
|
XML Java 数据库连接
Spring高手之路25——深入解析事务管理的切面本质
本篇文章将带你深入解析Spring事务管理的切面本质,通过AOP手动实现 @Transactional 基本功能,并探讨PlatformTransactionManager的设计和事务拦截器TransactionInterceptor的工作原理,结合时序图详细展示事务管理流程,最后引导分析 @Transactional 的代理机制源码,帮助你全面掌握Spring事务管理。
43 2
Spring高手之路25——深入解析事务管理的切面本质
|
3月前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
本指南介绍了如何在Spring Boot项目中集成Firebase云消息服务(FCM),包括创建项目、添加依赖、配置服务账户密钥、编写推送服务类以及发送消息等步骤,帮助开发者快速实现推送通知功能。
149 2
|
3月前
|
Java Spring 容器
Spring IOC、AOP与事务管理底层原理及源码解析
【10月更文挑战第1天】Spring框架以其强大的控制反转(IOC)和面向切面编程(AOP)功能,成为Java企业级开发中的首选框架。本文将深入探讨Spring IOC和AOP的底层原理,并通过源码解析来揭示其实现机制。同时,我们还将探讨Spring事务管理的核心原理,并给出相应的源码示例。
159 9
|
4月前
|
XML JavaScript Java
Spring Retry 教程
Spring Retry 是 Spring 提供的用于处理方法重试的库,通过 AOP 提供声明式重试机制,不侵入业务逻辑代码。主要步骤包括:添加依赖、启用重试机制、设置重试策略(如异常类型、重试次数、延迟策略等),并可定义重试失败后的回调方法。适用于因瞬时故障导致的操作失败场景。
Spring Retry 教程
|
3月前
|
开发框架 Java API
「SpringBrick快速入门指南」:一款基于Spring Boot的高级插件化开发框架
「SpringBrick快速入门指南」:一款基于Spring Boot的高级插件化开发框架
157 0
|
3月前
|
JSON Java Maven
实现Java Spring Boot FCM推送教程
详细介绍实现Java Spring Boot FCM推送教程
126 0
|
4月前
|
Java 数据库连接 数据库
Spring基础3——AOP,事务管理
AOP简介、入门案例、工作流程、切入点表达式、环绕通知、通知获取参数或返回值或异常、事务管理
|
5月前
|
Java Spring 开发者
掌握Spring事务管理,打造无缝数据交互——实用技巧大公开!
【8月更文挑战第31天】在企业应用开发中,确保数据一致性和完整性至关重要。Spring框架提供了强大的事务管理机制,包括`@Transactional`注解和编程式事务管理,简化了事务处理。本文深入探讨Spring事务管理的基础知识与高级技巧,涵盖隔离级别、传播行为、超时时间等设置,并介绍如何使用`TransactionTemplate`和`PlatformTransactionManager`进行编程式事务管理。通过合理设计事务范围和选择合适的隔离级别,可以显著提高应用的稳定性和性能。掌握这些技巧,有助于开发者更好地应对复杂业务需求,提升应用质量和可靠性。
58 0
|
5月前
|
SQL Java 数据库连接
Spring Boot联手MyBatis,打造开发利器:从入门到精通,实战教程带你飞越编程高峰!
【8月更文挑战第29天】Spring Boot与MyBatis分别是Java快速开发和持久层框架的优秀代表。本文通过整合Spring Boot与MyBatis,展示了如何在项目中添加相关依赖、配置数据源及MyBatis,并通过实战示例介绍了实体类、Mapper接口及Controller的创建过程。通过本文,你将学会如何利用这两款工具提高开发效率,实现数据的增删查改等复杂操作,为实际项目开发提供有力支持。
370 0
|
设计模式 Java 数据库连接
Spring(一)——【快速入门、配置文件、依赖注入以及API】
Spring(一)——【快速入门、配置文件、依赖注入以及API】
Spring(一)——【快速入门、配置文件、依赖注入以及API】