SSM框架学习-Spring事务管理入门

这篇具有很好参考价值的文章主要介绍了SSM框架学习-Spring事务管理入门。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

为了巩固所学的知识,作者尝试着开始发布一些学习笔记类的博客,方便日后回顾。当然,如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚,文章中如果有记录错误,欢迎读者朋友们批评指正。
(博客的参考源码可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)

发现宝藏

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【宝藏入口】。

1. Spring事务简介

一个数据库事务是一个被视为单一的工作单元的操作序列。这些操作应该要么完整地执行,要么完全不执行。事务管理是一个重要组成部分,RDBMS 面向企业应用程序,以确保数据完整性和一致性。事务的概念可以描述为具有以下四个关键属性说成是 ACID:

原子性:事务应该当作一个单独单元的操作,这意味着整个序列操作要么是成功,要么是失败的。

一致性:这表示数据库的引用完整性的一致性,表中唯一的主键等。

隔离性:可能同时处理很多有相同的数据集的事务,每个事务应该与其他事务隔离,以防止数据损坏。

持久性:一个事务一旦完成全部操作后,这个事务的结果必须是永久性的,不能因系统故障而从数据库中删除。

一个真正的 RDBMS 数据库系统将为每个事务保证所有的四个属性。使用 SQL 发布到数据库中的事务的简单视图如下:

使用 begin transaction 命令开始事务。

使用 SQL 查询语句执行各种删除、更新或插入操作。

如果所有的操作都成功,则执行提交操作,否则回滚所有操作。

Spring 框架在不同的底层事务管理 APIs 的顶部提供了一个抽象层。Spring 的事务支持旨在通过添加事务能力到 POJOs 来提供给 EJB 事务一个选择方案。Spring 支持编程式和声明式事务管理。EJBs 需要一个应用程序服务器,但 Spring 事务管理可以在不需要应用程序服务器的情况下实现,实现接口及实现类如下:

SSM框架学习-Spring事务管理入门

2. 入门案例–模拟银行间转账业务

1. 案例需求以及实现思路

SSM框架学习-Spring事务管理入门

2. 环境准备

  • 创建数据库表tbl_account

建表查询语句示例

create database spring_db;
use spring_db;

drop table if exists tbl_account;

create table tbl_account(
	id int primary key auto_increment,
	name varchar(20),
	money varchar(20)
);

INSERT INTO tbl_account VALUES (1, 'Tom', 1000);
INSERT INTO tbl_account VALUES (2, 'Jerry', 1000);

效果

SSM框架学习-Spring事务管理入门

  • 在pom.xml文件中导入坐标
 <dependencies>
    //spring框架
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>
    
    //druid数据源
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.1.16</version>
    </dependency>

    //mybatisa框架
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.6</version>
    </dependency>

    //数据库连接
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.47</version>
    </dependency>

    //spring操作jdbc
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>

    //spring整合mybatis
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.3.0</version>
    </dependency>

    //spring整合junit单元测试
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    
    //单元测试
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-test</artifactId>
      <version>5.2.10.RELEASE</version>
    </dependency>

  </dependencies>
  • 创建spring全局配置文件SpringConfig
 @Configuration
 @ComponentScan("com.itheima")
 @PropertySource("classpath:jdbc.properties")
 @Import({JdbcConfig.class,MybatisConfig.class})
 //开启注解式事务驱动
 @EnableTransactionManagement
 public class SpringConfig {
 }

  • 创建数据库信息文件jdbc.properties,填写数据库连接信息
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db?useSSL=false
jdbc.username=root
jdbc.password=root
  • 创建数据库连接配置类JdbcConfig
public class JdbcConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;

    @Bean
    public DataSource dataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }

    //配置事务管理器,mybatis使用的是jdbc事务
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
}
  • 创建mybatis创建SqlSessionFactory Bean 和 Mapper 代理开发映射对象配置文件MybatisConfig
public class MybatisConfig {

    @Bean
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource){
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        ssfb.setTypeAliasesPackage("org.example.domain");
        ssfb.setDataSource(dataSource);
        return ssfb;
    }

    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer(){
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("org.example.dao");
        return msc;
    }
}

  • 根据数据库表创建对应的实体类Account
public class Account{
    //此处省略getter、setter和toString方法
    private Integer id;
    private String name;
    private Double money;
    
}
  • 创建AccontDao接口,用注解的方式定义mapper代理开发业务接口,分别为加钱的操作方法 inmoney 和 减钱的操作 outmoney
public interface AccountDao {

    @Update("update tbl_account set money = money + #{money} where name = #{name}")
    void inMoney(@Param("name") String name, @Param("money") Double money);

    @Update("update tbl_account set money = money - #{money} where name = #{name}")
    void outMoney(@Param("name") String name, @Param("money") Double money);
}
  • 创建业务层接口AccountService,定义转账操作方法transfer
public interface AccountService {
    /**
     * 转账操作
     * @param out 传出方
     * @param in 转入方
     * @param money 金额
     */
    //配置当前接口方法具有事务
    @Transactional
    public void transfer(String out,String in ,Double money) ;
}

  • 创建业务层接口 AccountService 的实现类AccountServiceImpl,调用数据层功能的加钱和减钱方法 inmoney 和 outmoney
@Service
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;

    public void transfer(String out,String in ,Double money) {
        //减钱
        accountDao.outMoney(out,money);
        //加钱
        accountDao.inMoney(in,money);
    }

}

  • 编写测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {

    @Autowired
    private AccountService accountService;

    @Test
    public void testTransfer() throws IOException {
        //Tom 向 Jerry 转100元
        accountService.transfer("Tom","Jerry",100D);
    }

}
  • 程序运行结果

SSM框架学习-Spring事务管理入门
SSM框架学习-Spring事务管理入门

  • 文件结构参考

SSM框架学习-Spring事务管理入门

3. 入门案例分析

  • 入门案例完成了简单的模拟转账操作,此时我们在转账接口的实现类AccountServiceImpl减钱和加钱的操作中间添加一行模拟业务运行异常的代码,此时我们希望业务异常,终止操作,即数据库的账户余额不变。

  • 添加了模拟异常的代码及运行结果
    SSM框架学习-Spring事务管理入门
    SSM框架学习-Spring事务管理入门

SSM框架学习-Spring事务管理入门

  • 通过观察数据库中的表格数据我们发现异常前面的减钱操作运行了,而异常后面的加钱操作没有运行,导致整体业务功能失败。我们可以通过开启Spring事务来解决这个问题。

4. 小结

  • Spring注解式事务通常添加在业务层接口中而不会添加到业务层实现类中,降低耦合
  • 注解式事务可以添加到业务方法上表示当前方法开启事务,也可以添加到接口上表示当前接口所有方法开启事务
  • 事务管理器需要根据实现技术进行选择,mybatis使用的是jdbc事务

3. 开启Spring事务的一般步骤

1. @Transactional 注解配置对应的接口方法具有事务

    @Transactional
    public void transfer(String out,String in ,Double money) ;
}

2. 配置事务管理器,mybatis使用的是jdbc事务

public class JdbcConfig {
    @Bean
    public PlatformTransactionManager transactionManager(DataSource dataSource){
        DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
        transactionManager.setDataSource(dataSource);
        return transactionManager;
    }
}

3. @EnableTransactionManagement 注解开启注解式事务驱动

@EnableTransactionManagement
public class SpringConfig {

}

此时在存在模拟异常的情况下再次运行模拟测试类,数据库中的数据不变,业务功能运行正常,Spring事务开启成功。

4. Spring事务角色

1. Spring事务角色分为事务管理员和事务协调员

  • 事务管理员:发起事务方,在Spring中通常指代业务层开启事务的方法

  • 事务协调员:加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法

2. 结合入门案例分析

SSM框架学习-Spring事务管理入门

  • 在入门案例中,没加@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 设置事务传播行为

2. 添加事务属性格式举例

public interface AccountService {
    /**
     * 转账操作
     * @param out 传出方
     * @param in 转入方
     * @param money 金额
     */
    //配置当前接口方法具有事务
    @Transactional(readOnly = true,timeout = -1)
    public void transfer(String out,String in ,Double money) ;
}

3. 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);
    }

}

  • 运行模拟测试类

SSM框架学习-Spring事务管理入门
SSM框架学习-Spring事务管理入门

  • 观察数据库表我们发现,开启事务后在遇到抛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. 案例需求及实现思路

SSM框架学习-Spring事务管理入门

2. 编码环境准备

  • 创建数据库表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, '转账操作由TomJerry,金额:100.0', '20:55:49');

表格示例

SSM框架学习-Spring事务管理入门

  • 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事务代码

  • 文件结构示例

SSM框架学习-Spring事务管理入门

3. 用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,并执行测试类

SSM框架学习-Spring事务管理入门
SSM框架学习-Spring事务管理入门

SSM框架学习-Spring事务管理入门
SSM框架学习-Spring事务管理入门

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

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

SSM框架学习-Spring事务管理入门

  • 运行结果分析

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

  • 存在的问题:

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

SSM框架学习-Spring事务管理入门

  • 实现效果预期改进:

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

SSM框架学习-Spring事务管理入门

2. 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不会回滚。

3. 设置日志接口方法的事务传播行为属性

public interface LogService {
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    void log(String out, String in, Double money);
}
  1. 运行测试类观察效果

SSM框架学习-Spring事务管理入门
SSM框架学习-Spring事务管理入门
SSM框架学习-Spring事务管理入门
基于以上结果,Spring事务传播行为设置成功,业务功能运行正常。

`博客内容借鉴了bilibili黑马程序员SSM课程资料`

总结

欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下。
(博客的参考源码可以在我主页的资源里找到,如果在学习的过程中有什么疑问欢迎大家在评论区向我提出)文章来源地址https://www.toymoban.com/news/detail-454990.html

到了这里,关于SSM框架学习-Spring事务管理入门的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Spring 事务管理方案和事务管理器及事务控制的API

    Spring 事务管理方案和事务管理器及事务控制的API

    目录 一、事务管理方案 1. 修改业务层代码 2. 测试 二、事务管理器 1. 简介 2. 在配置文件中引入约束 3. 进行事务配置 三、事务控制的API 1. PlatformTransactionManager接口 2. TransactionDefinition接口 3. TransactionStatus接口 往期专栏文章相关导读  1. Maven系列专栏文章 2. Mybatis系列专栏文

    2024年02月08日
    浏览(13)
  • spring事务管理详解和实例(事务传播机制、事务隔离级别)

    spring事务管理详解和实例(事务传播机制、事务隔离级别)

    目录 1 理解spring事务 2 核心接口 2.1 事务管理器 2.1.1 JDBC事务 2.1.2 Hibernate事务 2.1.3 Java持久化API事务(JPA) 2.2 基本事务属性的定义 2.2.1 传播行为 2.2.2 隔离级别 2.2.3 只读 2.2.4 事务超时 2.2.5 回滚规则 2.3 事务状态 3 编程式事务 3.1 编程式和声明式事务的区别 3.2 如何实现编程式

    2024年02月06日
    浏览(12)
  • 【Spring】Spring的事务管理

    【Spring】Spring的事务管理

    Spring的事务管理简化了传统的事务管理流程,并且在一定程度上减少了开发者的工作量。 1.1 事务管理的核心接口 在Spring的所有JAR包中包含一个名为Spring-tx-4.3.6.RELEASE的JAR包,该包就是Spring提供的用于事务管理的依赖包。在该JAR包的org.Springframework.transaction包中有3个接口文件:

    2024年02月03日
    浏览(13)
  • Spring的事务管理

    1、事务的回顾 【1】事务的定义 是数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作,这些操作作为一个整体一起向系统提交,要么都执行、要么都不执行;事务是一组不可再分割的操作集合 【2】事务的ACID原则 事务具有4个基本特性:原子性、一致性

    2023年04月16日
    浏览(16)
  • Spring之事务管理

    Spring之事务管理

    事务是数据库操作最基本单位,要么都成功,要么都失败。 原子性 一致性 隔离性 持久性。 Spring定义了7种传播行为: 传播属性 描述 REQUIRED 如果有事务在运行,当前的方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行 REQUIRED_NEW 当前的方法必须

    2024年02月13日
    浏览(13)
  • Spring 事务管理

    Spring 事务管理

    目录 1. 事务管理 1.1. Spring框架的事务支持模型的优势 1.1.1. 全局事务 1.1.2. 本地事务 1.1.3. Spring框架的一致化编程模型 1.2. 了解Spring框架的事务抽象(Transaction Abstraction) 1.2.1. Hibernate 事务设置 1.3. 用事务同步资源 1.3.1. 高级同步方式 1.3.2. 低级同步方式 1.3.3.TransactionAwareDataSo

    2024年02月13日
    浏览(12)
  • Spring使用@Transactional 管理事务,Java事务详解。

    B站视频:https://www.bilibili.com/video/BV1eV411u7cg 技术文档:https://d9bp4nr5ye.feishu.cn/wiki/HX50wdHFyiFoLrkfEAAcTBdinvh 简单来说事务就是一组对数据库的操作 要么都成功,要么都失败。 事务要保证可靠性,必须具备四个特性:ACID。 A:原子性:事务是一个原子操作单元,要么完全执行,要么

    2024年02月11日
    浏览(9)
  • 【掌握Spring事务管理】深入理解事务传播机制的秘密

    【掌握Spring事务管理】深入理解事务传播机制的秘密

    🎉🎉🎉 点进来你就是我的人了 博主主页: 🙈🙈🙈 戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔 🤺🤺🤺 目录 1.Spring 中事务的实现方式 1.1 Spring 编程式事务 (了解) 1.2 Spring 声明式事务 ( @Transactional ) 【异常情况一】(自动回滚成功) 【异常情况二】(自动回滚失效

    2024年02月10日
    浏览(12)
  • Spring中的事务管理

    概念 事务 是一组操作的集合,它是一个不可分割的工作单位,这些操作要么 同时成功 ,要么 同时失败 。 操作 开启事务(一组操作 开始前 ,开启事务) : start transaction / begin ; 提交事务(这组操作 全部成功后 ,提交事务) : commit ; 回滚事务(中间任何一个操作 出现异常 ,

    2024年02月12日
    浏览(9)
  • Spring 事务管理详解及使用

    Spring 事务管理详解及使用

    ✅作者简介:2022年 博客新星 第八 。热爱国学的Java后端开发者,修心和技术同步精进。 🍎个人主页:Java Fans的博客 🍊个人信条:不迁怒,不贰过。小知识,大智慧。 💞当前专栏:SSM 框架从入门到精通 ✨特色专栏:国学周更-心性养成之路 🥭本文内容:一文吃透 Spring 中

    2024年01月20日
    浏览(19)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包