Spring-事务支持

目录

一、事务概述

二、引入事务场景

三、Spring对事务的支持 

Spring实现事务的两种方式

声明式事务之注解实现方式

    1.在Spring配置文件中配置事务管理器   

    2. 在Spring配置文件引入tx命名空间

    3. 在Spring配置文件中配置“事务注解驱动器”,通过注解的方式控制事务

    4. Service类或方法上添加@Transaction注解

    5.执行转账操作

声明式事务之全注解开发 

    1.配置类替代配置文件

    2.测试程序

    3.测试结果 

声明式事务之XML实现方式

    1.Spring配置文件

     2.编写测试程序

     3.测试结果


一、事务概述

  • 在一个业务流程中,通常需要多条DML语言共同联合完成,这多条DML语句必须同时成功或失败,这样才能保证数据的安全。
  • 事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。事务通常由高级数据库操纵语言或编程语言(如SQL,C++或Java)书写的用户程序的执行所引起,并用形如begin transaction和end transaction语句(或函数调用)来界定。事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。例如:在关系数据库中,一个事务可以是一条SQL语句,一组SQL语句或整个程序。
  • 事务的四个处理流程
  1. 开启事务(begin transaction)
  2. 执行核心业务代码
  3. 提交事务(业务执行过程没有出现异常) (commit transaction)
  4. 回滚事务(业务执行过程中出现异常)(rollback transaction)
  • 事务的ACID特性
  1. 原子性(Atomicity)事务小的工作单元,不可划分。
  2. 一致性(Consistency)事务要么同时成功,要么同时失败。
  3. 隔离性(Isolation)隔离性实际上解决的问题是多个事务作用于同一个或者同一批数据时的并发问题,防止由于交叉执行而导致数据的不一致。一个完美的事务隔离,在每个事务看来,整个系统只有自己在工作,对于整个系统而言这些并发的事务一个接一个的执行,也仿佛只有一个事务,这样的隔离成为“可序列化(Serializability)”。当然,这样的隔离级别会带来巨大的开销,因此出现了各种各样的隔离级别,进而满足不同场景的需要。
  4. 持久性(Durability)只要事务完成,不管发生任何问题,都不应该发生数据丢失。即,事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

二、引入事务场景

以银行转账为例 ,有两个账户act1 和 act2,act1向act2转账10000,对于这个流程包括两个操作,act1减10000,act2加10000,这两步必须同时成功或者同时失败。

  • 转账成功,act 减10000, act2 加 10000 
  • 转账失败,act减10000后,因系统故障,act2没有加10000

数据库为了避免这种特殊情况的发生,提出了事务概念。例如:通过jdbc连接数据库后,可以手动开启事务,提交事务,回滚事务。我们可以借助aop技术实现事务管理,更幸运的是Spring提供了事务支持。

三、Spring对事务的支持 

  • Spring实现事务的两种方式

  1. 编程式事务 通过编写代码的方式实现事务的管理
  2. 声明式事务 基于注解方式、XML配置方式
  • 声明式事务之注解实现方式

    1.在Spring配置文件中配置事务管理器   
<!--配置事务管理器--><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dateSource"/></bean>
    2. 在Spring配置文件引入tx命名空间
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    3. 在Spring配置文件中配置“事务注解驱动器”,通过注解的方式控制事务
<!--开启事务注解驱动器,开始事务注解。--><tx:annotation-driven transaction-manager="txManager"/>
    4. Service类或方法上添加@Transaction注解
package com.xxx.bank.service.impl;import com.xxx.bank.dao.AccountDao;
import com.xxx.bank.pojo.Account;
import com.xxx.bank.service.AccountService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;@Service("accountService")
@Transactional
public class AccountServiceImpl implements AccountService {@Resource(name = "accountDao")private AccountDao accountDao;@Overridepublic void transfer(String fromActno, String toActno, double money) {Account fromAct = accountDao.selectByActno(fromActno);if (fromAct.getBalance() < money) {throw new RuntimeException("余额不足,无法转账!!!");}Account toAct = accountDao.selectByActno(toActno);fromAct.setBalance(fromAct.getBalance() - money);toAct.setBalance(toAct.getBalance() + money);int count = accountDao.update(fromAct);count += accountDao.update(toAct);/*模拟异常String s = null;s.toString();*/if (count != 2) {throw new RuntimeException("转账失败,请联系银行...");}}
}
    5.执行转账操作

当前账户情况

执行一次转账

模拟异常情况,检查是否转账成功

  • 声明式事务之全注解开发 

    1.配置类替代配置文件
package com.zhj.bank;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;import javax.sql.DataSource;/*** @author zhj1259615665@qq.com* @create 2023-10-04 {16:45}*/
@Configuration
// 开启组件扫描
@ComponentScan("com.zhj.bank")
// 开启事务管理
@EnableTransactionManagement
public class Spring6Config {@Bean(name = "dataSource")public DruidDataSource getDataSource() {DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3307/spring");dataSource.setUsername("root");dataSource.setPassword("123456");return dataSource;}@Bean(name = "jdbcTemplate")public JdbcTemplate getJdbcTemplate(DataSource dataSource) {JdbcTemplate jdbcTemplate = new JdbcTemplate();jdbcTemplate.setDataSource(dataSource);return jdbcTemplate;}@Bean(name = "txManager")public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {DataSourceTransactionManager txManager = new DataSourceTransactionManager();txManager.setDataSource(dataSource);return txManager;}
}
    2.测试程序
@Testpublic void testNoXml() {ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Spring6Config.class);AccountService accountService = applicationContext.getBean("accountService", AccountService.class);try {accountService.transfer("act-001", "act-002", 10000);System.out.println("转账成功");} catch (Exception e) {e.printStackTrace();}}@Testpublic void test() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");AccountService accountService = applicationContext.getBean("accountService", AccountService.class);try {accountService.transfer("act-001", "act-002", 10000);System.out.println("转账成功");} catch (Exception e) {e.printStackTrace();}}
    3.测试结果 

  • 声明式事务之XML实现方式

    1.Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:tx="http://www.springframework.org/schema/tx"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!--开启组件扫描--><context:component-scan base-package="com.zhj.bank"/><!--配置数据源--><bean id="dateSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3307/spring"/><property name="username" value="root"/><property name="password" value="123456"/></bean><bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dateSource"/></bean><!--配置事务管理器--><bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dateSource"/></bean><!--配置通知,具体的增强代码--><tx:advice id="txAdvice" transaction-manager="txManager"><tx:attributes><tx:method name="transfer" propagation="REQUIRED"/></tx:attributes></tx:advice><!--配置切面--><aop:config><aop:pointcut id="txPointcut" expression="execution(* com.zhj.bank.service..*(..))"/><!--切面 = 切点 + 通知--><aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/></aop:config>
</beans>
     2.编写测试程序
public class BankTxTest {@Testpublic void test() {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");AccountService accountService = applicationContext.getBean("accountService", AccountService.class);try {accountService.transfer("act-001", "act-002", 10000);System.out.println("转账成功...");} catch (Exception e) {e.printStackTrace();}}
}
     3.测试结果

转账一次

模拟异常情况


        事务在数据库中是十分重要的概念,Spring提供了两种事务的支持方式,这篇博客记录了一点点的知识点,通过银行转账案例希望可以帮助你更好地理解事务。上述内容如果有错误的地方,希望大佬们可以指正。我一直在学习的路上,您的帮助使我收获更大!觉得对您有帮助的话,还请点赞支持!我也会不断更新文章!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/247223.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

容器技术发展史,编排与容器的技术演进之路——2

目录&#xff1a; 容器技术发展史 Jail时代 1979 年 贝尔实验室发明 chroot2000 年 FreeBSD 4.0 发行 FreeBSD Jail2001 年 Linux VServer 发行2004 年 Solaris Containers 发行云时代 2006 年 google 推出 Process Containers2008 年 LXC 推出2011 年 CloudFoundry 推出 Ward…

RH850P1X芯片学习笔记-Pin Functions

文章目录 Pin Connection Diagrams术语定义 Pin ListPort OverviewIntroductionFunctional OverviewPort CategoryOperation Mode运行模式 Port Function寄存器地址映射 Port寄存器描述Pn/JP0 — Port RegisterPPRn/JPPR0 — Port Pin Read RegisterPMn/JPM0 — Port Mode Regi…

apk和小程序渗透测试

apk和小程序渗透测试 文章目录 apk和小程序渗透测试小程序渗透测试apk和小程序的抓包安装证书apk渗透 小程序渗透测试 小程序的默认路径在 C:\Program Files (x86)\Tencent\WeChat\WeChatApp 使用UnpackMiniApp、wxappUnpacker工具完成逆向 先打开UnpackMiniApp.exe工具 选…

8.4 Windows驱动开发:文件微过滤驱动入门

MiniFilter 微过滤驱动是相对于SFilter传统过滤驱动而言的&#xff0c;传统文件过滤驱动相对来说较为复杂&#xff0c;且接口不清晰并不符合快速开发的需求&#xff0c;为了解决复杂的开发问题&#xff0c;微过滤驱动就此诞生&#xff0c;微过滤驱动在编写时更简单&#xff0c;…

重要通知丨JumpServer开源堡垒机V2社区版即将停止维护的通知

尊敬的JumpServer开源堡垒机用户&#xff1a;您好&#xff01; 如《关于JumpServer开源堡垒机V2版本产品生命周期的相关说明》所示&#xff0c;JumpServer开源堡垒机V2版本&#xff08;社区版&#xff09;将于2023年12月31日停止维护支持。 在过去两年多的时间里&#xff0c;…

MYSQL练题笔记-聚合函数-有趣的电影

一、题目相关内容 1&#xff09;相关的表和题目 2&#xff09;帮助理解题目的示例&#xff0c;同时告诉我查询结果的格式 二、自己初步的理解 其实从题目就可以看出来&#xff0c;三个关键点&#xff0c;非&#xff0c;奇数&#xff0c;降序排列。 我去找下奇数的函数是哪一…

接口压测指南

接口压测指南 一、 为什么需要进行接口压测二 、接口压测的目标是什么三、 用什么工具进行接口压测四、 接口压测核心指标4.1 JMeter的报告模板4.2 ApiPost报告模板 五、 接口慢如何排查5.1 大体排查思路5.2 排查工具5.3 压测经验 一、 为什么需要进行接口压测 突然有一天领导…

在用户不安装 ImageMagick 的情况下使用

需要以编程的方式配置环境变量&#xff08;手工配置也是一样的效果&#xff09; 1、首先要配置 path 将 {ImageMagick目录} 配置到path中 2、配置 MAGICK_HOME 将 {ImageMagick目录} 配置到MAGICK_HOME中 3、配置MAGICK_CODER_MODULE_PATH 将 {ImageMagick目录}\modules\…

JVM:双亲委派(未完结)

类加载 定义 一个java文件从编写代码到最终运行&#xff0c;必须要经历编译和类加载的过程&#xff0c;如下图&#xff08;图源自b站视频up主“跟着Mic学架构”&#xff09;。 编译就是把.java文件变成.class文件。类加载就是把.class文件加载到JVM内存中&#xff0c;得到一…

大模型技术的发展与实践

一、大模型的概念 大型语言模型&#xff0c;也称大语言模型、大模型&#xff08;Large Language Model&#xff0c;LLM&#xff1b;Large Language Models&#xff0c;LLMs) 。 大语言模型是一种深度学习模型&#xff0c;特别是属于自然语言处理&#xff08;NLP&#xff09;的…

【五分钟】熟练使用numpy.cumsum()函数(干货!!!)

引言 numpy.cumsum()函数用于计算输入数组的累积和。当输入是多维数组时&#xff0c;numpy.cumsum()函数可以沿着指定轴计算累积和。 计算一维数组的累计和 代码如下&#xff1a; # 计算一维数组的累计和 tmp_array np.ones((4,), dtypenp.uint8) # [1, 1, 1, 1] print(&…

3.镜像加速器

目录 1 阿里云 2 网易云 从网络上拉取镜像的时候使用默认的源可能会慢&#xff0c;用国内的源会快一些 1 阿里云 访问 阿里云-计算&#xff0c;为了无法计算的价值 然后登录&#xff0c;登录后搜索 容器镜像服务 点击容器镜像服务 点击管理控制台 点击 镜像工具->镜像…