Spring事务传播特性实例解析(以及如何使用注解形式事务)

事务Transactional传播机制 mandatory:强制性的。suspend:暂停、终止。 阅读详情

原文地址:http://blog.youkuaiyun.com/yoara/article/details/16114853
原文地址的文章,写的demo会误导读者,所以在原文地址文章的基础上对原作者的demo进行修改,让demo浅显易懂。

Demo说明

采用Junit4.10.0+Spring4.2.0+Spring JDBCTemplate+mysql5.1.51(数据库表的存储引擎使用 InnoDB,MyISAM存储引擎是不支持事务的),通过注解方式配置事务,代码层次包括主测试类,两个Service对象,事务在Service开启。

事务概念

注意:从原文地址中,COPY 过来的。
本地事务
数据库事务,默认事务为自动提交,因此如果一个业务逻辑类中有多次数据库操作将无法保证事务的一致性。

Spring事务
对本地事务操作的一次封装,相当于把使用JDBC代码开启、提交、回滚事务进行了封装。
上述两个概念会在demo中用到,以方便大家理解代码。

传播特性
该特性是保证事务是否开启,业务逻辑是否使用同一个事务的保证。当事务在传播过程中会受其影响。其传播特性包括:
1、Propagation.REQUIRED
方法被调用时自动开启事务,在事务范围内使用则使用同一个事务,否则开启新事务。
2、Propagation.REQUIRES_NEW
无论何时自身都会开启事务
3、Propagation.SUPPORTS
自身不会开启事务,在事务范围内则使用相同事务,否则不使用事务
4、Propagation.NOT_SUPPORTED
自身不会开启事务,在事务范围内使用挂起事务,运行完毕恢复事务
5、Propagation.MANDATORY
自身不开启事务,必须在事务环境使用否则报错
6、Propagation.NEVER
自身不会开启事务,在事务范围使用抛出异常
7、Propagation.NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中. 如果没有活动事务, 则按TransactionDefinition.PROPAGATION_REQUIRED 属性执行。需要JDBC3.0以上支持。

代码实例

代码说明,两个 实例类,InsertPassword 、 InsertUser, InsertPassword类中的insertPassWord方法 调用了 InsertUser类中的 insertUser 方法。

测试代码

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.sky.lp.AAtestTransaction.InsertPassword;

public class TestJunit {
    @Test
    public void testTransaction() {
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-servlet.xml");
        InsertPassword t  = (InsertPassword)appCtx.getBean("insertPassword");
        t.insertPassWord();
    }

}

InsertPassword类代码

package com.sky.lp.AAtestTransaction;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Component
public class InsertPassword {

    @Autowired
    private JdbcTemplate jdbc;

    @Autowired
    private InsertUser insertUser;

    @Transactional(propagation = Propagation.REQUIRED)
    public void insertPassWord() {
        String[] sql = new String[2];
        sql[0] = "INSERT INTO PASSWORD (USERID, PASSWORD, CREATE_TIME)  VALUES  ('1','qwe', now())";
        jdbc.execute(sql[0]);
        insertUser.insertUser();
        throw new RuntimeException("抛错");
    }

}

InsertUser类代码

package com.sky.lp.AAtestTransaction;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Component
public class InsertUser {

    @Autowired
    private JdbcTemplate jdbc;

    @Transactional(propagation = Propagation.REQUIRED)
    public void insertUser() {
        String[] sql = new String[2];
        sql[0] = "INSERT INTO user (name, age, CREATE_TIME) VALUES  ('123456789','25', now())";
        jdbc.execute(sql[0]);
    }

}

spring-servlet.xml 配置文件

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:tx="http://www.springframework.org/schema/tx" xmlns:util="http://www.springframework.org/schema/util"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/context
      http://www.springframework.org/schema/context/spring-context-3.0.xsd
      http://www.springframework.org/schema/mvc
      http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
        http://www.springframework.org/schema/aop
    http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/util 
      http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <!-- 启动包扫描功能,以便注册带有@Controller、@Service、@repository、@Component等注解的类成为spring的bean -->
    <context:annotation-config />
    <context:component-scan base-package="com.sky.lp.AAtestTransaction" />

    <!-- 定义数据源 使用 c3po 包 -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"
        init-method="init" destroy-method="close">
        <property name="name" value="druidOne" />
        <property name="url" value="jdbc:mysql://localhost:3306/littledemo" />
        <property name="username" value="root" />
        <property name="password" value="laixu785^@#"></property>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="initialSize" value="2" />
        <property name="maxActive" value="10" />
        <property name="minIdle" value="5" />
        <property name="validationQuery" value="SELECT COUNT(*) FROM DUAL" />
        <property name="testWhileIdle" value="true" />
        <property name="timeBetweenEvictionRunsMillis" value="5000" />
    </bean>

    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 事务控制 -->  
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <tx:annotation-driven transaction-manager="transactionManager" />

</beans>

传播特性 Propagation.REQUIRED

在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.REQUIRED)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.REQUIRED)。

经测试无论在insertPassWord方法还是insertUser方法,如果有一个方法抛出运行时异常,数据提交失败。 这说明insertPassWord和insertUser使用的是同一个事务,并且只要方法被调用就开启事务。

传播特性 Propagation.REQUIRES_NEW

在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.REQUIRES_NEW)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.REQUIRES_NEW)。

经测试无论在insertPassWord方法还是insertUser方法,如果其中一个方法抛出运行时异常,不会影响另一个方法事务的数据提交。 这说明insertPassWord和insertUser使用的是不的同事务。

传播特性 Propagation.SUPPORTS

在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.SUPPORTS)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.SUPPORTS)。

经测试如果在insertPassWord中抛出异常,password数据和user数据都被正确提交。说明insertPassWord和insertUser没有被spring管理和开启事务,而是使用了本地事务,由于本地事务默认自动提交因此数据都提交成功,但它们使用的却不是同一个事务,一旦出现异常将导致数据的不一致。

传播特性 Propagation.NOT_SUPPORTED

在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.REQUIRED)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.NOT_SUPPORTED)。

方法 insertPassWord 注释掉 抛错代码,insertUser 在方法末尾 添加

throw new RuntimeException("抛错");

经测试如果在insertUser 中抛出异常,passwrod数据提交失败,user数据提交成功。说明insertPassWord开启了事务,insertUser没有开启事务,而是使用了本地事务。

传播特性 Propagation.MANDATORY

在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.SUPPORTS)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.MANDATORY)。

insertPassWord 方法 和 insertUser 方法 都注释掉 抛错 代码

经测试报错

org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'

说明 方法 insertUser 必须在事务内执行。

传播特性 Propagation.NEVER

在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.REQUIRED)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.NEVER)。

insertPassWord 方法 和 insertUser 方法 都注释掉 抛错 代码

经测试报错

org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never'

说明 方法 insertUser 不能在事务内执行。

传播特性 Propagation.NESTED

在 InsertPassword类中的insertPassWord方法 上 添加@Transactional(propagation = Propagation.NESTED)。在 InsertUser类中的insertUser方法 上 添加@Transactional(propagation = Propagation.NESTED)。

方法 insertPassWord在方法末尾添加

throw new RuntimeException("抛错");

经测试代码报错,user数据和password数据都没有提交成功。说明其按照REQUIRED特性运行。对于嵌套事务,大家可以模拟两个数据源,一方的失败不会影响另一方。

基于opencv人脸识别实现课堂抬头率检测系统 完整代码 可直接运行 作为毕设 阅读详情

相关推荐

【AWS】创建aws云服务器EC2实例

本文介绍了如何创建aws的EC2云服务器,并介绍了如何使用Xshell远程连接上云服务器

Marcos921的博客 2502

事物的传播行为

1.在外围方法未开启事务的情况下Propagation.REQUIRED修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。 2.在外围方法开启事务的情况下Propagation.REQUIRED修饰的内部方法会加入到外围方法的事务中,所有Propagation.REQUIRED修饰的内部方法和外围方法均属于同一事务,只要一个方法回滚,整个事务均回滚.抛出异常或者异常捕获到都回滚 3.在外围方法未开启事务的情况下Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,

weixin_41202749的博客 378

(2024,DDPM,DDIM,流匹配,SDE,ODE)扩散:基础教程

本文的目标是尽可能简单地教授扩散。第一节介绍扩散的基本原理。第二节和第三节展示如何构建随机和确定性扩散采样器。第四部分介绍了密切相关的流匹配,可看作是扩散的推广。​第五节,强调实践中最重要的一些设计选择,包括采样器、噪声时间表和参数化方法。

qq_44681809的博客 1万+

聊一聊Spring事务中的7种传播特性

methodA和methodB,如果methodA调用methodB,那么将采用什么样的事务形式,这就叫做事务的传播特性,传播特性是作用于内层方法。目前,Spring在/*** PROPAGATION_REQUIRED:如果不存在外层事务,就主动创建事务;否则使用外层事务* PROPAGATION_REQUIRES_NEW:总是主动开启事务;如果存在外层事务,就将外层事务挂起* PROPAGATION_NESTED:如果不存在外层事务,就主动创建事务;否则创建嵌套的子事务。

竹林幽深 821

Qt中多线程的使用(一)

我们要实现的是读取大文件qtgui.index的内容加入文本框中。 很容易想到的方法: QFile* file = new QFile("E:\qtgui.index"); file-&gt;open(QIODevice::ReadOnly); QTextStream *stream = new QTextStream(file); while(!st...

yao5hed的专栏 1万+

用Stata复现经典文献:上市公司全要素生产率(TFP)计算全流程(含LP/OP代码解读)

本文提供了使用Stata软件复现上市公司全要素生产率(TFP)计算的完整实战指南。重点解读了主流的Levinsohn-Petrin(LP)和Olley-Pakes(OP)半参数估计方法,通过详细的数据清洗、变量构建与价格平减步骤,手把手演示了如何准确测算TFP,并强调了LP方法在处理中国上市公司数据时的稳定性和适用性。

b0c1d2的博客 596

Spring的事务传播特性

事务属性的种类:传播行为、隔离级别、只读和事务超时。事务传播行为就是多个事务方法相互调用时,事务如何在这些方法间传播。

qq_37933128的博客 2409

【WRF模拟】土地利用类型的确定:最大覆盖法/瓦片法

土地利用类型的确定:最大覆盖法/瓦片法

WW、forever的博客 1529

【Spring学习34】Spring事务(4):事务属性之7种传播行为

事务传播行为什么叫事务传播行为?听起来挺高端的,其实很简单。 即然是传播,那么至少有两个东西,才可以发生传播。单体不存在传播这个行为。事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。 例如:methodA事务方法调用methodB事务方法时,methodB是继续在调用者methodA的事务中运行呢,还是为自己开启一个

程序老兵的博客 1万+

从0到1构建数据分析AI Agent:数据采集、洞察生成与报告自动化

在企业数字化转型的今天,数据分析师80%的时间被消耗在重复取数、数据清洗、报表排版等低价值劳动上,真正用于深度业务洞察和决策支持的时间不足20%。本文将从核心概念、技术原理、代码实现、落地实践全维度,教你从0到1搭建一套完整的数据分析AI Agent系统,实现「用户用自然语言提需求→Agent自动采集多源数据→AI自动挖掘业务洞察→自动生成符合业务要求的多格式报告」的全链路自动化,平均可将需求响应速度从天级压缩到分钟级,释放70%以上的分析师人力成本。

AI Python 编程之道的博客 473

uniapp - 详细手机端h5网页调用手机摄像头进行二维码识别扫描,在uniapp的H5移动端微信网页平台中,在浏览器中调用手机扫码功能详细教程,识别二维码并获取扫描结果(完整示例源码,一键复制即用

uniapp,h5,手机端网页,H5手机网页,uniapp开发h5实现扫码功能,uniapp微信h5网页扫码sdk使用教程,uniapp h5网页如何实现浏览器扫码,uniapp扫码功能怎么兼容h5_uniapph5怎么做扫码功能,uniapp的手机网页如何实现扫二维码一维码,浏览器H5实现js扫码,H5调用摄像头和扫一扫功能,亲测可用,H5调用本地摄像头实现扫一扫,uni-h5项目解决扫码功能,uniapp实现微信H5扫码,解决uniapp在H5端使用不能扫码问题,uni-app的h5扫码(二维码、条形码

✅ 精选推荐文章 1万+

Spring中的7大事务传播特性

Spring中的7大事务传播特性

qq_36311757的博客 1201

innovus:addRepeaterByRule用法

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧?addRepeaterByRule不管transition/timing violation,只根据约束的length/cap/fanout等等去给net 插buffer。

m0_61544122的博客 1093

Spring事务注解

spring注解事务特性介绍,失效场景总结

严文文 Chris 8969

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Spring中事务传播机制和@Transational注解在Spring中的使用

本文介绍了Spring事务传播机制和@Transactional注解的使用。详细说明了7种事务传播行为(REQUIRED、REQUIRES_NEW等)的特点和区别,重点分析了NESTED嵌套事务的实现原理。同时深入解析了@Transactional注解的各项属性配置,包括传播行为、隔离级别、超时设置、只读模式、异常回滚规则等。文章还提供了实际的代码示例,展示了在类和方法上使用@Transactional注解。

Java开发,分享日常技术学习,有对网络安全感兴趣的可以交流 779

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

深入理解 @Transactional 注解与 Spring 事务机制

在企业级应用开发中,数据的一致性和完整性至关重要,事务管理则是保障这一目标的关键技术。Spring 框架提供的 @Transactional 注解为开发者带来了便捷的声明式事务管理方式,极大地简化了事务处理的复杂性。本文将深入剖析 @Transactional 注解的使用细节、Spring 事务传播规则,并结合实际案例与源码分析,助力开发者全面掌握这一核心技术。

diligent_man_z的博客 1242

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

spring7大事务传播行为

众所周知,spring有编程式事务与声明式事务(通过springAOP实现),声明式事务又分为两种实现方式,一种xml文件形式,一种注解形式,而声明式事务又有七大事务传播行为 spring7大事务传播行为 事务传播行为通俗的讲,就是两个或以上的事务方法进行调用时,各种不同的表现形式 事务是数据库操作原子性的最基本手段,而事务的传播级别和数据隔离级别,是事务控制的两个主要特性。传播级别定义的是事务的控制范围,事务隔离级别定义的是事务在数据库读写方面的控制范围。上篇文章主要分析了隔离级别的问题,这

z_ssyy的博客 2126

关于Spring事务的隔离级别,传播行为,及其管理配置

关于Spring事务的隔离级别,传播行为,及其管理配置

weixin_43515260的博客 706

Spring事务传播行为

种,REQUIRED,如果当前存在事务,则加入,否则创建一个新的。其他不常见的就不多提了,就是围绕有事务,无事务,嵌套,以及异常来分不同情况选择事务创建。NESTED传播是Spring事务管理中的一个精巧设计,通过数据库的保存点机制实现了"事务中的事务",既提供了细粒度的事务控制,又避免了新建连接的开销。如果methodB被调用时已经有一个事务存在,该事务将被挂起,直到methodB的事务完成。如果当前没有事务,则创建一个新的事务。总是以非事务方式执行,如果当前存在事务,则挂起当前事务。

埃泽漫笔 494

【Spring】事务传播级别详解

在日常开发中,事务的应用是一个绕不开的话题,我们经常会在对于数据库的操作代码里应用到事务。事务的编写和控制是一些很繁琐,且与业务无关的代码,需要非常小心。不过幸运的时,我们实际在开发中并不需要每次应用事务时都自行负责整个事务代码的编写。借助于spring提供的事务管理功能,我们只需要通过少量的配置,就可以让自己的业务方法拥有事务的特性。利益于spring事务管理优秀的设计,我们可以专注于业务代码的编写,在引入事务管理时,基本上可以做到对于业务代码没有侵入性。

金哥的博客 323

Spring事务详解

本文系统梳理了Spring事务的核心知识,主要包含以下内容:1) 事务的ACID特性(原子性、一致性、隔离性、持久性);2) Spring事务管理机制,包括PlatformTransactionManager、TransactionDefinition和TransactionStatus三大核心接口;3) 事务属性详解,重点解析传播行为(7种)和隔离级别(4种);4) @Transactional注解的使用要点和常见失效场景;5) 事务最佳实践建议。文章通过理论结合实践的方式,帮助开发者深入理解Spring

2301_80248554的博客 983

第六章:Springmvc事务管理和配置文件xml详解和七大事务和注解@Transactional

1.事务配置为事务配置管理即为DataSourceTransactionManager类中dataSource属性赋值2.配置事务通知,通知指的是动作,自定义哪些字符串开头的命名方法添加事务动作。3.将这些事务动作放在哪些位置或者哪个点上?即配置pointcut,像交警一样设卡查哨这里边的expression中execution(public * com.xxx.service..(…))表达式4.配置事务切面即将配置好的事务通知和事务的切点交给事务管理。

beiback的博客 2858

Spring 注解详解:@Service 与 @Transactional

职责分离@Service负责组件识别,负责事务管理精准控制:推荐在方法级别使用,实现更精细的事务控制避免陷阱:注意内部方法调用导致的事务失效问题合理配置:根据业务需求设置合适的回滚规则和传播行为通过遵循这些最佳实践,您可以构建出更加健壮、可维护的 Spring 应用程序。

倚肆的博客 1015

Spring——声明式事务

Spring的声明式事务使用起来比较简单,只要在方法的上方添加@Transactional注解,就将一个方法变成事务方法了。使用声明式事务,可以将事务管理代码从业务方法中抽离出来(也就是不用在方法里写commit和rollback),以声明的方式来实现事务管理。 Spring的核心事务管理抽象是PlatformTransactionManager,要想使用声明式事务,必须先在xml中先将其声明为b...

Stay Hungry Stay Foolish 574

Spring的事务传播性与隔离级别

Spring的事务传播性与隔离级别   一、事务的四个特性 l  原子性:一个事务中所有对数据库的操作是一个不可分割的操作序列,要么全做,要么全部做。 l  一致性:数据不会因为事务的执行而遭到破坏。 l  隔离性:一个事务的执行,不受其他事务(进程)的干扰。既并发执行的个事务之间互不干扰。 l  持久性:一个事务一旦提交,它对数据库的改变将是永久的。   二、事务的实现方式  

yang1982_0907的专栏 7085

Spring的事务传播机制

Spring事务传播机制定义了事务方法相互调用时的行为规则,主要包括七种传播行为: REQUIRED(默认):存在事务则加入,否则新建 REQUIRES_NEW:新建独立事务,挂起当前事务 SUPPORTS:存在事务则加入,否则非事务执行 MANDATORY:必须存在事务,否则抛异常 NOT_SUPPORTED:非事务执行,挂起当前事务 NEVER:必须非事务执行,否则抛异常 NESTED:嵌套事务(依赖数据库保存点支持) 默认的REQUIRED适合大多数场景,REQUIRES_NEW用于独立操作(如日志记

mojinchuan的专栏 125
上一篇: spring AOP 基于注解(spring版本4.2.0)
下一篇: Mysql5.1中主要使用的几种表引擎?它们的区别是什么?在使用表引擎时,要注意什么问题?
三易的博客
博客等级 码龄15年 42粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值