spring笔记⑬——spring事务

article/2025/9/13 16:36:15

事务的四个特征

CAID是事务的四个特征,所有事务都必须满足以下特性。

  • 原子性(Atomicity):一个事务要么全部执行,要么不执行
  • 一致性(Consistency):事务的运行并不改变数据库中数据的一致性
  • 隔离性(Isolation):事务的隔离性也称作独立性,是指两个以上的事务不会出现交错执行的状态。因为这样可能会导致数据不一致。
  • 持久性(Durtability):事务执行成功以后,该事务对数据库所作的更改便是持久的保存在数据库之中,不会无缘无故的回滚。

数据库隔离级别

  • READ UNCOMMITTED:不可提交读
  • READ CONMMITTED:可提交读
  • REPEATABLE READ:可重复读
  • SERIAIZABLE:序列化

查询数据库隔离级别的sql语句

select @@global.tx_isolation

各种场景

下面是不同隔离级别各种场景出现的问题,括号内的是默认隔离级别的数据库

隔离级别脏读不可重复读幻读
READ UNCOMMITTED
READ CONMMITTED(Sql Server , Oracle)×
REPEATABLE READ(MySQL)××
SERIAIZABLE×××

各种场景的详细分析

spring事务

spring事务总共有两种,编程式事务和声明式事务,其中编程式事务因为代码具有侵入性,开发效率很慢,所以很少会在开发中应用,仅作了解。

编程式事务了解

声明式事务

可以通过两种方法开启和使用,分别是基于xml的和基于注解的

基于xml

在spring的applicationContext.xml配置文件中加入下面三类配置

<!-- spring中基于XML的声明式事务控制配置步骤1、配置事务管理器2、配置事务的通知此时我们需要导入事务的约束 tx名称空间和约束,同时也需要aop的使用tx:advice标签配置事务通知属性:id:给事务通知起一个唯一标识transaction-manager:给事务通知提供一个事务管理器引用3、配置AOP中的通用切入点表达式4、建立事务通知和切入点表达式的对应关系5、配置事务的属性是在事务的通知tx:advice标签的内部-->
<!-- 一:配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property>
</bean><!-- 二:配置事务的通知-->
<tx:advice id="txAdvice" transaction-manager="transactionManager"><!-- 配置事务的属性isolation:用于指定事务的隔离级别。默认值是DEFAULT,表示使用数据库的默认隔离级别。propagation:用于指定事务的传播行为。默认值是REQUIRED,表示一定会有事务,增删改的选择。查询方法可以选择SUPPORTS。read-only:用于指定事务是否只读。只有查询方法才能设置为true。默认值是false,表示读写。timeout:用于指定事务的超时时间,默认值是-1,表示永不超时。如果指定了数值,以秒为单位。rollback-for:用于指定一个异常,当产生该异常时,事务回滚,产生其他异常时,事务不回滚。没有默认值。表示任何异常都回滚。no-rollback-for:用于指定一个异常,当产生该异常时,事务不回滚,产生其他异常时事务回滚。没有默认值。表示任何异常都回滚。测试:no-rollback-for="java.lang.ArithmeticException",遇到算数异常不回滚--><tx:attributes><tx:method name="*" propagation="REQUIRED" read-only="false"/><tx:method name="find*" propagation="SUPPORTS" read-only="true"></tx:method></tx:attributes>
</tx:advice><!-- 三:配置aop-->
<aop:config><!-- 配置切入点表达式--><aop:pointcut id="pc" expression="execution(* com.itheima.service..*.*(..))"></aop:pointcut><!--建立切入点表达式和事务通知的对应关系 --><aop:advisor advice-ref="txAdvice" pointcut-ref="pc"></aop:advisor>
</aop:config>

基于注解

首先需要开启spring事务,这个只需要在spring配置类上面加上@EnableTransactionManagement注解就可以了

/*** @EnableTransactionManagement用以开启spring事务* 同样也开启了事务的传播特性*/
@Configuration
@EnableTransactionManagement
public class SpringConfig {/*** 配置数据源* @return*/@Beanpublic DataSource dataSource(){DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis");dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUsername("root");dataSource.setPassword("454424");return dataSource;}/*** 配置事务管理器* 将数据源注入* @param dataSource* @return*/@Beanpublic DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource){DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();dataSourceTransactionManager.setDataSource(dataSource);return dataSourceTransactionManager;}/*** 配置jdbcTemplate* 同样需要注入数据源* @param dataSource* @return*/@Beanpublic NamedParameterJdbcTemplate namedParameterJdbcTemplate(DataSource dataSource){NamedParameterJdbcTemplate namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(dataSource);return namedParameterJdbcTemplate;}
}

对于想要加上spring事务传播特性的事务方法只需要在方法上加上@Transactional注解就可以了,可以指定事务的传播特性。

@Component
public class PersonDaoImpl implements PersonDao {@AutowiredNamedParameterJdbcTemplate template;@Override@Transactional(propagation = Propagation.REQUIRED)public void update() {int update = template.update("insert into person(person_id,name,person_addr,gender) values(5,'cc','pp',1)", new HashMap<String, Object>());}
}

注意,事务的传播特性默认是REQUIRED
在这里插入图片描述

spring的事务传播特性

事务传播行为类型说明
PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

需要注意的是,如果方法中出现异常就会回滚,但是如果已经将异常捕捉住(try/catch),那么在捕捉的那一层就不会回滚数据。

jdk动态代理带来的spring事务失效

在同一个类中spring事务失效的问题
https://blog.csdn.net/bntX2jSQfEHy7/article/details/79040349

在事务方法中执行其他的事务方法和直接调用事务方法会出现两种情况
因为在事务方法中调用的其他事务方法其实是原方法,而直接调用事务方法其实已经是被spring通过jdk动态代理的代理对象,在代理对象中实现了事务的开启与提交,但是如果调用的原生方法就不会开启事务
所以在这种情况下如果在事务方法调用的事务方法抛出异常,可是如果调用的原生方法,所以因为没有开启事务,就没能回滚数据

@Component
public class PersonDaoImpl implements PersonDao {@AutowiredNamedParameterJdbcTemplate template;@Override@Transactional(propagation = Propagation.REQUIRED)public void update() {int update = template.update("insert into person(person_id,name,person_addr,gender) values(5,'cc','pp',1)", new HashMap<String, Object>());try {update1();} catch (Exception e) {e.printStackTrace();}}@Transactional(propagation = Propagation.REQUIRES_NEW)public void update1() {int update = template.update("insert into person(person_id,name,person_addr,gender) values(6,'zz','dd',1)", new HashMap<String, Object>());System.out.println(1/0);}
}

解决方法有
1.实现ApplicationContextAware接口得到applicationContext对象,然后如果要在事务方法在中调用其他的事务方法,那么可以从applicationContext获得bean对象(就是代理对象),直接调用bean对象的事务方法,不过这种方法比较麻烦
2.

@Component
public class PersonDaoImpl implements PersonDao, ApplicationContextAware {ApplicationContext applicationContext;@AutowiredNamedParameterJdbcTemplate template;@Override@Transactional(propagation = Propagation.REQUIRED)public void update() {int update = template.update("insert into person(person_id,name,person_addr,gender) values(5,'cc','pp',1)", new HashMap<String, Object>());try {//通过bean对象调用方法,这样这个方法就是代理方法applicationContext.getBean(PersonDao.class).update1();} catch (Exception e) {e.printStackTrace();}}@Transactional(propagation = Propagation.REQUIRES_NEW)public void update1() {int update = template.update("insert into person(person_id,name,person_addr,gender) values(6,'zz','dd',1)", new HashMap<String, Object>());System.out.println(1/0);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}
}

http://chatgpt.dhexx.cn/article/bWSH2aYS.shtml

相关文章

SQL查询语句(内联,as,in,通配符)

最近在学习牛腩新闻发布系统&#xff0c;正如牛老师所说&#xff0c;作为一个优秀的.NET开发人员&#xff0c;对SQL语句不熟怎么能行呢&#xff0c;接下来就总结下牛老师写的存储过程中SQL语句&#xff0c;挺经典&#xff0c;举一反三 首先先展示出来适用于系统的三张表 新闻类…

【微信小程序 | 实战开发】配置微信小程序APPID并快速接入

写在前面: 你是否想要掌握人工智能的最新技术和应用?你是否想要成为未来社会的创新者和领导者?你是否想要和全球的优秀导师和同学一起学习和交流?如果你的答案是肯定的,那么欢迎来到床长人工智能教程网站,这里是你实现梦想的起点! 个人名片: 🐼作者简介:一名大一在校…

获取苹果收集设备ID的方法

目录 问题 解决 问题 如果我们想要通过工具获取苹果手机 iPhone 或者 iPad 的设备 ID&#xff0c;也就是 UDID。这个时候&#xff0c;很多人可能会问 UDID 是什么&#xff0c;UDID 是 iOS 设备的一个唯一识别码&#xff0c;每台 iOS 设备都有一个独一无二的编码&#xff0c;…

浅谈大数据广告下个人隐私保护,开发者视角的广告原理

本文已收录于 Github CodeClass 和 Gitee CodeClass 致力于打造高质量编程学习课堂&#xff0c;内含百篇原创技术文章&#xff0c;千本计算机开源电子书&#xff0c;谷歌、阿里大神开源 LeetCode 题解&#xff0c;各类编程学习资源&#xff0c;欢迎 star &#xff0c;一起学习&…

简单理解MySQL的存储引擎

1、什么是存储引擎&#xff1f; 在说明存储引擎之前&#xff0c;首先你需要简单了解MqSQL的整体架构。 从上图可知&#xff0c;存储引擎位于整体架构的最底层。 存储引擎真正负责了MySQL中数据的存储和提取。 可以这样理解&#xff1a; 其实我们平时写的各种SQL语句相当于指…

iOS隐私新规如何破局?盗版SKAdnetwork可行吗?

背景&#xff1a;   在2020年的开发者大会上&#xff0c;苹果宣布iOS14设备将会在App首次打开时主动弹窗请求是否选择允许广告追踪&#xff0c;即被获取设备的IDFA。这也就意味着新系统需要用户手动选择允许&#xff0c;而旧系统是手动选择关闭&#xff0c;这一关键改变无异…

牛腩新闻发布--过程或函数 'news_selectByCaId' 需要参数 '@caid',但未提供该参数(一)

发现问题 今天敲击牛腩,在敲击Web页面的List.aspx之后,点击Ctrl+F5运行,发现运行不了,首先是数据库中调取数据有问题,因为这个数据是用存储过程调取的,所以需要修改存储过程,这时候只需要改成如下代码就行: 将这个更改完之后就可以在数据库中调取到应需要的数据了,但是…

【牛腩】DELETE 语句与 REFERENCE 约束“FK_news_category“冲突。该冲突发生于数据库“newssystem“,表“dbo.news“, column ‘caId‘

【前言】 牛腩中删除类别的时候会提示受到主外键的约束&#xff0c;导致无法删除这个类别。 【问题描述】 DELETE 语句与 REFERENCE 约束"FK_news_category"冲突。该冲突发生于数据库"newssystem"&#xff0c;表"dbo.news", column ‘caId’。…

【牛腩】过程或函数 ‘news_selectByCaId‘ 需要参数 ‘@caid‘,但未提供该参数

【前言】 在运行牛腩的时候会有提示过程或者函数缺少参数。这个是因为存储过程中写的缺少参数&#xff0c;添加相应的参数就可以了。 【问题描述】 过程或函数 ‘news_selectByCaId’ 需要参数 ‘caid’&#xff0c;但未提供该参数 过程或函数 ‘news_selectByContent’ 需要…

关于IDFA、CAID和「5. 1.2 - Data use sharing」

今天&#xff0c;2021年3月18日&#xff0c;突然收到了之前从未遇到过的拒审邮件&#xff0c;邮件原文如下&#xff1a; 发件人 Apple 5. 1.2 - Data use & sharing Please review this information carefully as it impacts your app’s availability on the App Store a…

中国广告协会的CAID方案

前些时间看到一个消息&#xff0c;腾讯、百度和字节跳动测试工具绕开苹果的ATT&#xff08;AppTrackingTransparency&#xff0c;简称 ATT&#xff0c;旨在保护用户隐私的应用追踪透明度框架&#xff09;&#xff0c;估计这个应该是在测试CAID。 过一两天又出现一个消息&#x…

微信H5链接包装

最近看到好多人问一个问题&#xff0c;就是在微信中发游戏链接给好友&#xff0c;让链接显示成一个抖音的样式&#xff0c;如下&#xff1a; 这种链接包装&#xff0c;做起来说难不难&#xff0c;说简单也不简单。网上很多服务商都可以做&#xff0c;不过靠谱程度就参差不齐了…

微信内 H5 页面自定义分享

起源&#xff1a; 最近公司在做一个活动的h5页面&#xff0c;在微信内打开时需要进行微信授权&#xff0c;然后后端会重定向到这个页面并且携带了一些参数&#xff08;openid等&#xff09;。问题是点击微信的原生分享时&#xff0c;会把携带的这些参数一起分享出去&#xff0…

H5容器技术方案

●●● Native开发原生应用是手机操作系统厂商&#xff08;目前主要是苹果的iOS和google的Android&#xff09;对外界提供的标准化的开发模式&#xff0c;他们对于native开发提供了一套标准化实现和优化方案。但是他们存在一些硬伤&#xff0c;比如App的发版周期偏长、有时无法…

H5的分享功能

在H5的 页面分享该活动给好友&#xff0c;代码如下&#xff1a; 1&#xff1a;需要添加 js引用&#xff1a; <script srchttp://res.wx.qq.com/open/js/jweixin-1.2.0.js></script> 2&#xff1a;需要添加对象&#xff1a; var wx require("weixin-js-sdk…

微信小程序共享元素+ page-container假页实现弹出效果

1.实现效果 2.实现原理 page-container page-container 小程序如果在页面内进行复杂的界面设计&#xff08;如在页面内弹出半屏的弹窗、在页面内加载一个全屏的子页面等&#xff09;&#xff0c;用户进行返回操作会直接离开当前页面&#xff0c;不符合用户预期&#xff0c;预期…

小程序与h5分享

小程序分享 可以参考小程序文档小程序文档链接 介绍&#xff1a;小程序中有直接在按钮上面加open-type就会触发分享了 如下: <button open-type"share"></button>在onShareAppMessage这个生命周期上面书写你要分享的内容就可以了&#xff0c; 如下&…

小程序嵌套 h5 并分享给朋友

1.先准备一个https地址&#xff0c;用于在微信公众平台/小程序中/开发管理/开发设置/业务域名 中设置 主要是后续要用到 web-view 组件 2.在小程序中设置跳转信息 task/index.vue this.graceJS.navigate(“/pagesA/task/sharePage?pathyes&houseName”houseName“&ty…

H5页面设置微信分享

H5页面设置微信分享 写代码之前的准备工作 1、登录微信公众号&#xff08;需要已经认证过的公众号&#xff09;&#xff0c;进入“设置与开发”→“公众号设置”→“功能设置”→“JS接口安全域名”&#xff0c;将文件下载下来&#xff0c;上传至与将要分享的页面相同的域名服务…

闲置电视盒子不要扔!搭建Blynk物联网服务器,太香了!

之前写过WINDOS搭建blynk物联网的教程&#xff0c;由于电脑一直开机功耗太大&#xff0c;现在终于找到了用电视机顶盒刷linux系统安装服务器的方法&#xff0c;先一睹为快 在开始今天的折腾前&#xff0c;自备一个刷好linux系统的电视机顶盒&#xff0c;可以按神雕的教程来 地…