Spring声明式事务使用详情(知识点+案例)

目录

1、声明式事务的概念

2、Spring事务管理器

3、基于注解的Spring事务

4、Spring事务属性

4.1只读(Read-Only)

4.2事务超时(Timeout)

4.3事务异常回滚(rollbackFor)

4.4事务隔离级别(Isolation Level)

4.5事务的传播行为(Propagation)

在数据库操作中,事务是一组操作的集合,要么全部成功,要么全部失败。事务管理的目标是确保数据一致性和完整性。Spring 提供了强大的事务管理功能,简化了事务处理的复杂性。

1、声明式事务的概念

事务主要分为两类,一类是编程式事务,一类是声明式事务

编程式事务是指手动编写程序来管理事务,即通过编写代码的方式直接控制事务的提交和回滚。

比如下面的例子

Connection conn = ...;
  
try {
    // 开启事务:关闭事务的自动提交
    conn.setAutoCommit(false);
    // 核心操作
    // 业务代码
    // 提交事务
    conn.commit();
  
}catch(Exception e){
  
    // 回滚事务
    conn.rollBack();
  
}finally{
  
    // 释放数据库连接
    conn.close();
  
}

编程式事务具体操作过程中,所有细节都需要程序员自己来完成,比较繁琐,且代码复用性不高。

声明式事务是指使用注解或 XML 配置的方式来控制事务的提交和回滚

开发者只需要添加配置即可, 具体事务的实现由第三方框架实现,避免我们直接进行事务操作!

使用声明式事务可以将事务的控制和业务逻辑分离开来,提高代码的可读性和可维护性。

2、Spring事务管理器

在Spring框架中,事务管理器(Transaction Manager)是一个核心组件,它负责管理和控制事务的边界,确保数据的一致性和完整性。Spring提供了多种事务管理器,用于不同的事务处理场景和技术栈。

事务管理器的主要职责包括:

  • 管理事务的边界:确定事务的开始和结束,以及事务的提交或回滚。
  • 集成事务资源:如数据源、消息队列等,确保这些资源能够参与到事务中来。
  • 控制事务的传播行为:在复杂的事务调用场景中,控制事务的传播行为,如是否需要在现有事务中运行、是否需要创建新事务等。
  • 管理事务的隔离级别:设置事务的隔离级别,以防止并发事务之间的干扰。
  • 处理异常和回滚:在事务执行过程中,如果遇到异常,则根据事务的属性决定是否需要回滚事务。

Spring为不同的持久化技术提供了不同的事务管理器实现类,如:

  • DataSourceTransactionManager:用于JDBC和MyBatis等基于JDBC的持久化技术。
  • JpaTransactionManager:用于JPA(Java Persistence API)的持久化技术。
  • HibernateTransactionManager:专门用于Hibernate的持久化技术。
  • JmsTransactionManager:用于JMS(Java Message Service)消息队列的事务管理。

我们现在要使用的事务管理器是DataSourceTransactionManager,将来整合 JDBC方式、JdbcTemplate方式、Mybatis方式的事务实现!

DataSourceTransactionManager类中的主要方法:

  • doBegin():开启事务
  • doSuspend():挂起事务
  • doResume():恢复挂起的事务
  • doCommit():提交事务
  • doRollback():回滚事务

3、基于注解的Spring事务

入门案例

第一步:导入依赖

Spring声明式事务对应依赖
    - spring-tx: 包含声明式事务实现的基本规范(事务管理器规范接口和事务增强等等)
    - spring-jdbc: 包含DataSource方式事务管理器实现类DataSourceTransactionManager
    - spring-orm: 包含其他持久层框架的事务管理器实现类例如:Hibernate/Jpa等

<!-- 数据库驱动 和 连接池-->
  <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>8.0.25</version>
  </dependency>

  <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid</artifactId>
      <version>1.2.8</version>
  </dependency>

  <!-- spring-jdbc -->
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>6.0.6</version>
  </dependency>

  <!-- 声明式事务依赖-->
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>6.0.6</version>
  </dependency>

第二步:配置事务管理器

配置要声明事务的数据库

第三步:使用声明事务注解@Transactional

第四步:调用

4、Spring事务属性

4.1只读(Read-Only

对一个查询操作来说,如果我们把它设置成只读,就能够明确告诉数据库,这个操作不涉及写操作。这样数据库就能够针对查询操作来进行优化。

设置方式

// readOnly = true把当前事务设置为只读 默认是false!
@Transactional(readOnly = true)

把事务设置成已读的话,接下来就只能进行数据库查询语句,不能进行数据库增删改。

补充:@Transactional注解放在类上,则事务会影响到类中的每一个方法。除非在方法上又设置了 @Transactional 注解。对一个方法来说,离它最近的 @Transactional 注解中的事务属性设置生效。

4.2事务超时(Timeout)

 事务在执行过程中,有可能因为遇到某些问题,导致程序卡住,从而长时间占用数据库资源。而长时间占用资源,大概率是因为程序运行出现了问题(可能是Java程序或MySQL数据库或网络连接等等)。此时这个很可能出问题的程序应该被回滚,撤销它已做的操作,事务结束,把资源让出来,让其他正常程序可以执行。概括来说就是一句话:超时回滚,释放资源。

timeout设置事务超时时间,单位秒! 默认: -1 永不超时,不限制事务时间!

4.3事务异常回滚(rollbackFor)

默认只针对运行时异常回滚,编译时异常不回滚

我们可以设置事务所有异常回滚,rollbackFor =Exception.class

rollbackFor属性:指定哪些异常类才会回滚,默认是 RuntimeException and Error 异常方可回滚!

/**
 * timeout设置事务超时时间,单位秒! 默认: -1 永不超时,不限制事务时间!
 * rollbackFor = 指定哪些异常才会回滚,默认是 RuntimeException and Error 异常方可回滚!
 * noRollbackFor = 指定哪些异常不会回滚, 默认没有指定,如果指定,应该在rollbackFor的范围内!
 */
@Transactional(readOnly = false,timeout = 3,rollbackFor = Exception.class)
public void changeInfo() throws FileNotFoundException {
    studentDao.updateAgeById(100,1);
    //主动抛出一个检查异常,测试! 发现不会回滚,因为不在rollbackFor的默认范围内! 
    new FileInputStream("xxxx");
    studentDao.updateNameById("test1",1);
}
4.4事务隔离级别(Isolation Level)

    数据库事务的隔离级别是指在多个事务并发执行时,数据库系统为了保证数据一致性所遵循的规定。常见的隔离级别包括:

  •     读未提交(Read Uncommitted):事务可以读取未被提交的数据,容易产生脏读、不可重复读和幻读等问题。实现简单但不太安全,一般不用。
  •     读已提交(Read Committed):事务只能读取已经提交的数据,可以避免脏读问题,但可能引发不可重复读和幻读。
  •     可重复读(Repeatable Read):在一个事务中,相同的查询将返回相同的结果集,不管其他事务对数据做了什么修改。可以避免脏读和不可重复读,但仍有幻读的问题。
  •     串行化(Serializable):最高的隔离级别,完全禁止了并发,只允许一个事务执行完毕之后才能执行另一个事务。可以避免以上所有问题,但效率较低,不适用于高并发场景。

    不同的隔离级别适用于不同的场景,需要根据实际业务需求进行选择和调整。

4.5事务的传播行为(Propagation)

在 Spring 事务管理中,事务的传播行为(Transaction Propagation)定义了一个事务方法被另一个事务方法调用时,事务如何传播。

我们通过propagation属性去设置它的传播

事务传播propagation的默认值是REQUIRED

REQUIRED:如果父方法有事务,就加入,如果没有就新建自己独立!(就是说,如果父方法下调用的其他事务,如果其他事务异常回滚了,我也要跟着回滚,这是一个整体)

REQUIRES_NEW:不管父方法是否有事务,我都新建事务,都是独立的(如果父方法下调用的其他事务,如果其他事务异常回滚了,我们不用跟着回滚,我们是独立执行的)

注意:在同一个类中,对于@Transactional注解的方法调用,事务传播行为不会生效。这是因为Spring框架中使用代理模式实现了事务机制,在同一个类中的方法调用并不经过代理,而是通过对象的方法调用,因此@Transactional注解的设置不会被代理捕获,也就不会产生任何事务传播行为的效果

  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值