Spring详细解读事务管理

目录
  • 什么是事务
  • Spring事务配置
  • Spring事务传播行为
    • 1. PROPAGATION_REQUIRED
    • 2. PROPAGATION_SUPPORTS
    • 3. PROPAGATION_REQUIRES_NEW
  • 声明式事务失效

什么是事务

事务就是对数据库若干操作组成的一个单元

我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作的结合。由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻辑并未正确的完成,之前成功操作数据的并不可靠,需要在这种情况下进行回退

事务的作用就是为了保证用户的每一个操作都是可靠的,事务中的每一步操作都必须成功执行,只要有发生异常就回退到事务开始未进行操作的状态,这些操作要么都完成,要么都取消,从而保证数据满足一致性的要求

如何理解呢 ?

例如 :  A现在要转账给B  那么转账是几个方法呢? 两个 : 方法1: A 减钱  方法2: B加钱

如果A方法成功执行后 , B方法中执行时出现了异常, 就等于A钱扣了却没有给B加钱, 那么这样的行为肯定是不允许的, 所以我们引入事务的概念 , 事务一般也是对于数据库而言的

Spring事务配置

Spring事务管理又分为编程式事务和声明式事务

编 程 式 事 务 在 项 目 中 很 少 使 用 , 这 种 方 式 需 要 注 入 一 个 事 务 管 理 对 象 TransactionTemplate ,然后在我们代码中需要提交事务或回滚事务时自己写代码实现

声明式事务管理建立在 AOP 基础上,本质是对方法前后进行拦截,所以声明式事务是方法级别的。

为什么说是基于AOP呢? 因为在通过xml文件配置中我们是这样来做的

<aop:config>
<aop:pointcut expression="execution(* com.ff.spring.service.UserService.*(..))" id="allmethod"/>
<aop:advisor advice-ref="txadvice" pointcut-ref="allmethod"/>
</aop:config>

基于注解的方式直接帮我们省略了这个过程, 更为方便

这里我们主要介绍声明式事务

首先在db.xml中配置spring事务管理类

<!--配置spring事务管理类-->
    <bean id="sourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="druidDataSource"/>
    </bean>

这里我们直接介绍基于注解方式的spring事务管理

开启注解扫描

<!-- 开启注解事务管理 -->
<tx:annotation-driven transaction-manager="sourcetransactionManager"/>

我们使用@Transactiona  这样一个注解标签来声明事务, 它可以作用于方法,表明这个方法支持事务, 也可以作用于类, 表明这个类中的所有方法支持事务

public class UserDao {
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Transactional(propagation= Propagation.REQUIRED)
    public void saveUser(){
        jdbcTemplate.update("insert into admin(account,pass_word,sex) values (?,?,?)","li","111","男");
        int i=108/0;  //出现异常
        jdbcTemplate.update("insert into admin(account,pass_word,sex) values (?,?,?)","qw","111","男");
    }
}

在上述代码中, 第一条sql 语句虽然成功执行, 但后面出现了异常, 所以这个方法的事务并没有提交, 是不会向数据库提交数据的

Spring事务传播行为

即然是传播,那么至少有两个东西,才可以发生传播。单体不存在传播这个行为。事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。事务传播行为是 Spring 框架独有的事务增强特性,他不属于的事务实际提供方数据库行为.

是不是有点懵, 说啥呢这是, 接着来解释

试想 , 有两个方法 A 和 B , 它们都有事务, 那么我在 A 方法中去调用 B 方法, 那么B方法此时

应该怎样去执行呢? 是将B 方法加入到 A 方法组成一个事务,还是它们都是一个独立的事务呢 ?

Spring定义了 7种 事务传播行为, 我们下面主要介绍其中三种,都会举例说明

传播行为一般是对于B方法(被调用的方法而言的)

1. PROPAGATION_REQUIRED

指定的方法必须在事务内执行,若当前存在事务,加入到当前事务中,若当前没有事务,则创建一个新事务,这种传播行为是最常见的,也是 spring 默认的传播行为

A 方法调用 B方法(PROPAGATION_REQUIRED) , 如果A方法是存在事务的, 那么直接将B方

法加入到 A事务中,组成一个事务.  如果 A 方法是没有事务的, 那么B就是一个单独的事务

这么说可能有点绕 , 我们再次请出李雷, 算了, 这次就放过李雷, 换成张三吧

就是说呢 , 我和李雷现在都要去吃饭, 然后我说呢,李雷咱俩一起吧(A调用B,我叫李雷去吃饭) , 不出意外的话(事务顺利执行提交), 我们两吃饭作为一个整体, 最终都吃了饭(AB都存在事务就作为一个整体事务) , 但是还有一种情况, 我叫李雷去吃饭, 但是我却没有去(A调用B, 但是A没有事务),那么这时候李雷肯定单独去吃饭(B单独开启一个事务)

@Transactional(propagation = Propagation.REQUIRED)
    public void saveDept(){   //A调用B
        deptDao.saveDept();
        commonService.saveLog(); //B
    }
@Transactional(propagation = Propagation.REQUIRED)
    public void saveLog(){
        commonDao.saveLog();
        int a = 10/0; //异常
    }

此时 A 调用 B , 它们都有事务, B中出了异常, 那么此时AB最终都不会去和数据库交互

//@Transactional(propagation = Propagation.REQUIRED)
    public void saveDept(){   //A调用B
        deptDao.saveDept();
        commonService.saveLog(); //B
    }
@Transactional(propagation = Propagation.REQUIRED)
    public void saveLog(){
        commonDao.saveLog();
        int a = 10/0; //异常
    }

第二种方式 , 我们将异常加到A 中, 注释掉注解(取消A的事务), 那么此时B是单独的一个事务, B里面出了异常, 不会去和数据库交互, 则A会去和数据库交互

2. PROPAGATION_SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行

A方法调用B方法(PROPAGATION_SUPPORTS), 如果A是存在事务的,那么直接将B方

法加入到 A事务中,组成一个事务. 如果 A 没有事务, 那么B也没有事务

我叫李雷去吃饭 , 如果我一定要去吃饭(A调用B), 那么最终我吃饭和李雷吃饭就总共作为一个事务,就和上面第一个例子是一样的, 作为整体的一个事务. 但是第二种情况就是, 我虽然叫了李雷去吃饭, 但是我最终没有去(A没有事务) , 这时候李雷说, 那我也不去吃饭了(B也没有事务)

@Transactional(propagation = Propagation.REQUIRED)
    public void saveDept(){   //A调用B
        deptDao.saveDept();
        commonService.saveLog(); //B
    }
@Transactional(propagation = Propagation.SUPPORTS)
    public void saveLog(){
        commonDao.saveLog();
        int a = 10/0; //异常
    }

此时 A调用 B , AB都有事务, 那么B 中出现异常, 最终都不会和数据库交互,就和上述第一种情况

一样

//@Transactional(propagation = Propagation.REQUIRED)
    public void saveDept(){   //A调用B
        deptDao.saveDept();
        commonService.saveLog(); //B
    }

取消掉A 的事务 , 那么此时B 会以非事务执行 , 这时候AB都会和数据库去交互,因为非事务

3. PROPAGATION_REQUIRES_NEW

总是新建一个事务,如果当前存在事务,把当前事务挂起,直到新建的事务结束。

A方法调用B方法(PROPAGATION_REQUIRES_NEW), 如果A存在事务, 那么B此时会先把A事务挂起, 然后为自己新建一个事务, 先执行完B事务, 才会去执行 A 事务 . 如果A 没有事务, 那么B自己单独新建一个事务执行

这里就是, 我虽然叫李雷去吃饭(A调用B) , 李雷都会先自己去吃饭, 不等我(B自己新建一个事务, A有事务先将A挂起)

@Transactional(propagation = Propagation.REQUIRED)
    public void saveDept(){   //A调用B
        deptDao.saveDept();
        commonService.saveLog(); //B
    }
@Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveLog(){
        commonDao.saveLog();
        int a = 10/0; //异常
    }

A 调用 B , A支持事务 , 此时B将A事务挂起, 单独开启一个事务,里面出现异常,此时AB都不会和数据库交互

//@Transactional(propagation = Propagation.REQUIRED)
    public void saveDept(){   //A调用B
        deptDao.saveDept();
        commonService.saveLog(); //B
    }

取消A的事务, 但此时B事务是独立的, 出现异常, 所以B不会和数据库交互,但是A和数据库交互

声明式事务失效

事务也是会失效的 , 失效有以下几种情况

1.@Transactional 应用在非 public 修饰的方法上

2.@Transactional 注解属性 propagation 设置错误

3.同一个类中方法调用,导致@Transactional 失效

4.异常被 catch 捕获导致@Transactional 失效

5.数据库引擎不支持事务

非public修饰导致权限错误, 事务失效,  propagation设置参数错误导致事务失效

同类下方法调用也会导致事务失效

catch如果捕获了异常, 就相当于程序没有异常,这时事务也会失效

最后就是数据库引擎不支持, mysql中只有InnoDB引擎是支持事务的

结语

关于Spring 事务管理就先说到这 , 后面介绍SpringMVC 与 ssm 框架, 谢谢,爱你们学 spring 一定要笑, 笑着学 ,嘿嘿

到此这篇关于Spring详细解读事务管理的文章就介绍到这了,更多相关Spring事务管理内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Spring事务管理原理及方法详解

    这篇文章主要介绍了Spring事务管理原理及方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 事务,在日常开发或者面试中都必定会涉及到.开发工作中,结合数据库开发理解就是:一组dml要么全部成功执行提交,要么因为某一个操作异常,撤销之前所做的成功的操作,整体执行失败.再简单点的一句话:生死与共. 由此,可以看出,事务的必要性:在开发工作中,保证操作数据的安全性.事务的控制也就是保证数据的访问安全性. 一.事务的四大特性 A:原子性(ato

  • Spring对事务管理的支持

    Spring对事务的支持有两种方式,一是自己编写事务,精确控制事务的边界,二是采用声明事务的方式,使用AOP来完成.无论哪种方式,我们都将使用一个Spring事务管理连接器连接特定平台的事务实现. Spring不直接管理事务,相反,它提供很多可供选择的事务管理器,将事务管理的责任委托给JTA(Java Transaction Interface)或相应的持久性机制所提供的某个特定平台事务实现. Spring提供的常用的事务管理器有DataSourceTransactionManager,Hibe

  • Spring事务管理方法步骤解析

    1.Spring的事务管理主要包括3个接口 TransactionDefinition:封装事务的隔离级别,超时时间,是否为只读事务和事务的传播规则等事务属性,可通过XML配置具体信息. PlatformTransactionManager:根据TransactionDefinition提供的事务属性配置信息,创建事务. TransactionStatus:封装了事务的具体运行状态.比如,是否是新开启事务,是否已经提交事务,设置当前事务为rollback-only等. 2.Spring的事务管理

  • 详解Springboot事务管理

    在Spring Boot事务管理中,实现自接口PlatformTransactionManager. public interface PlatformTransactionManager { org.springframework.transaction.TransactionStatus getTransaction(org.springframework.transaction.TransactionDefinition transactionDefinition) throws org.

  • Spring事务管理配置文件问题排查

    在开发中,遇到了sql语句报错,但是并没有回滚的情况. 经过几天的排查,终于找到了事务没有回滚的原因. 原来的项目用的是informix的数据库,原来针对事务回滚的机制都是好用的.我本地用的是mysql数据库. 先将程序代码与spring-mybatis.xml配置文件拿过来: 1.程序代码: 这个问题是在验证增删改查返回值时发现的. 两个操作,删除时,因为关联了外键,所以会报错,此时正常情况更新的语句也会回滚,但是并没有. /** *@Author: Administrator on 2020

  • Spring中的事务管理如何配置

    这篇文章主要介绍了spring中的事务管理如何配置,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 在springboot中,使用事务非常的简单,因为springboot已经帮我们配置好了,只需要加上注解@Transactional即可 在spring中我们需要做一些配置:主要有三点: @Transactional:在相应的方法上加上这个注解 @EnableTransactionManagement:在配置类中加上,开启事务管理 需要在配置类中加

  • 五分钟教你手写 SpringBoot 本地事务管理实现

    白菜Java自习室 涵盖核心知识 1. SpringBoot 事务 一直在用 SpringBoot 中的 @Transactional 来做事务管理,但是很少没想过 SpringBoot 是如何实现事务管理的,今天从源码入手,看看 @Transactional 是如何实现事务的,最后我们结合源码的理解,自己动手写一个类似的注解来实现事务管理,帮助我们加深理解. 1.1. 事务的隔离级别 事务为什么需要隔离级别呢?这是因为在并发事务情况下,如果没有隔离级别会导致如下问题: 脏读 (Dirty Re

  • Spring中事务管理的四种方法(银行转账为例)

    前言 本文配套示例代码下载地址(完整可运行,含sql文件,下载后请修改数据库配置):点击这里下载 一.事务的作用 将若干的数据库操作作为一个整体控制,一起成功或一起失败. 原子性:指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生. 一致性:指事务前后数据的完整性必须保持一致. 隔离性:指多个用户并发访问数据库时,一个用户的事务不能被其他用户的事务所干扰,多个并发事务之间数据要相互隔离. 持久性:指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,即时数据库发生故障也不应

  • Spring的事务管理你了解吗

    目录 1.事务介绍 2.事务的四个特性(ACID) 3.Spring 事务管理的核心接口 4.PlatformTransactionManager 事务管理器 5.TransactionStatus 事务状态 6.TransactionDefinition 基本事务属性的定义 一.传播行为: 二.隔离级别: 三.只读 四.事务超时 五.回滚规则 7.Spring 编程式事务和声明式事务的区别 8.不用事务实现转账 第一步:创建Java工程并导入相应的 jar 包 第二步:编写 Dao 层 第三步

  • Spring详细解读事务管理

    目录 什么是事务 Spring事务配置 Spring事务传播行为 1. PROPAGATION_REQUIRED 2. PROPAGATION_SUPPORTS 3. PROPAGATION_REQUIRES_NEW 声明式事务失效 什么是事务 事务就是对数据库若干操作组成的一个单元 我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作的结合.由于数据操作在顺序执行的过程中,任何一步操作都有可能发生异常,异常会导致后续操作无法完成,此时由于业务逻辑并未正确的完成,之前成功操作数

  • Spring详细讲解事务失效的场景

    目录 1)未被Spring管理 2)数据库引擎不支持事务 3)事务方法没有被public修饰 4)方法使用final修饰 5)同一类中方法调用 6)未开启事务 7)多线程调用 8)错误的传播行为 9)自己try…catch…掉了异常 10)手动抛出了错误的异常 11)自定义回滚异常 12)嵌套事务回滚多了 1)未被Spring管理 使用Spring事务的前提是:对象要被Spring管理,事务方法所在的类要被加载为bean对象 如果事务方法所在的类没有被加载为一个bean,那么事务自然就失效了,示

  • SpringBoot超详细讲解事务管理

    目录 1. 事务的定义 2. 事务的特性 3. 事务的隔离性 4. 事务管理 5. 示例 1. 事务的定义 事务是由 N 步数据库操作序列组成的逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行. 2. 事务的特性 事务的 ACID 特性: 原子性:事务是应用中不可分割的最小执行体 一致性:事务执行的结果必须使得数据从一个一致性状态转变为另一个一致性状态 隔离性:各个事务的执行互不干扰,任何事务的内部操作对其他事务都是隔离的 持久性:事务一旦提交,对数据所做的任何修改都要记录到永久存储器中

  • Spring中的事务管理实例详解

    本文实例讲述了Spring中的事务管理.分享给大家供大家参考.具体分析如下: 事务简介: 事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性 事务就是一系列的动作,它们被当作一个单独的工作单元.这些动作要么全部完成,要么全部不起作用 事务的四个关键属性(ACID) ① 原子性(atomicity):事务室一个原子操作,有一系列动作组成.事务的原子性确保动作要么全部完成,要么完全不起作用 ② 一致性(consistency):一旦所有事务动作完成,事务就被提交.数据和资源就

  • 详谈Spring框架之事务管理

    一.编程式事务 二.声明式事务 1.基于XML的事务 1.1 Spring配置文件 <!-- 配置c3p0数据源,只是进行了最简单的配置 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="user" value="root"></property>

  • Spring+SpringMVC配置事务管理无效原因及解决办法详解

    一般我们在Spring的配置文件application.xml中对Service层代码配置事务管理,可以对Service的方法进行AOP增强或事务处理如事务回滚,但是遇到一个问题,在Controller类中调用Service层方法,配置的事务管理会失效,查询相关资料发现原因.其实Spring和SpringMVC俩个容器为父子关系,Spring为父容器,而SpringMVC为子容器.也就是说application.xml中应该负责扫描除@Controller的注解如@Service,而Spring

  • spring声明式事务管理解析

    前沿:通过对spring事务管理有了比较深入学习,本文将不做实例,而是指定具体的类和配置文件进行讲解. 本文内容: 1.了解什么是声明式事务? 2.声明式事务管理分别有哪几种? 3.这几种事务管理之间的区别是什么? 一.什么是声明式事务? 声明式事务(declarative transaction management)是spring提供的对程序事务管理的方式之一.Spring的声明式事务就是采用声明的方式来处理事务,用在Spring配置文件中声明式的处理事务来代替代码式的处理事务.这样的好处是

  • spring学习JdbcTemplate数据库事务管理

    目录 spring JdbcTemplate数据库事务管理 一.spring 中的事务管理 二.spring 事务管理 API 三.使用事务管理 1. 配置文件 2. 类上添加事务注解 spring JdbcTemplate数据库事务管理 现在有个账户表,里面存着用户金额. 如果要真正地做好转账的操作,就要用到事务,否则当出现异常后会出现数据不一致等问题. try { // 第一步 开启事务 // 第二步 进行业务操作 // 第三步 没有发生异常,提交事务 } catch(){ // 第四步 发

随机推荐