spring事务管理快速入门(以转账为例)

spring事务管理(以转账为例)

概述

Spring事务管理提供了一种在应用程序中管理事务的机制,它抽象了底层的事务管理细节,使得开发者可以更加专注于业务逻辑的实现,而不必过多关心事务的处理。以下是Spring事务管理的一般概述:

  1. 事务的概念: 事务是一组操作,它们被看作一个不可分割的工作单元,要么全部执行成功,要么全部不执行。在数据库中,事务通常用于确保数据库的一致性和完整性。

  2. Spring事务抽象: Spring提供了一个强大的事务管理抽象,它包括两个核心概念:事务管理器(TransactionManager)事务定义(TransactionDefinition)

    • 事务管理器(TransactionManager): 是一个接口,它负责事务的启动、提交和回滚。Spring有多个实现类,可以适用于不同的事务管理场景。

    • 事务定义(TransactionDefinition): 定义了事务的属性,如隔离级别、传播行为、超时等。Spring允许通过XML或注解的方式来配置事务的属性。

  3. 声明式事务管理: Spring支持声明式事务管理,这意味着你可以通过配置文件或注解的方式来声明事务,而不必在代码中显式编写事务管理的逻辑。

    • XML配置方式: 通过XML配置文件中的 元素来声明事务。

    • 注解配置方式: 使用 @Transactional 注解来标注需要事务管理的方法,然后通过配置启用注解驱动事务管理。

  4. 编程式事务管理: 除了声明式事务管理外,Spring还支持编程式事务管理,这意味着你可以在代码中显式控制事务的开始、提交和回滚。

    • 使用 TransactionTemplate 类: Spring提供了 TransactionTemplate 类,它封装了事务的基本操作,你可以在代码中使用它来编程式地管理事务。

  5. 事务传播行为: 在Spring中,事务的传播行为(Transaction Propagation Behavior)定义了在一个事务方法被另一个事务方法调用时,应该如何处理事务。Spring定义了七种事务传播行为:

    1. PROPAGATION_REQUIRED(默认):

      • 如果当前存在事务,则加入该事务;如果不存在事务,则创建一个新的事务。这是最常见的传播行为。

    2. PROPAGATION_SUPPORTS:

      • 如果当前存在事务,则加入该事务;如果不存在事务,则以非事务的方式执行。

    3. PROPAGATION_MANDATORY:

      • 如果当前存在事务,则加入该事务;如果不存在事务,则抛出异常。要求外部调用方必须在事务中调用。

    4. PROPAGATION_REQUIRES_NEW:

      • 无论当前是否存在事务,都创建一个新的事务。如果有事务存在,将它挂起。

    5. PROPAGATION_NOT_SUPPORTED:

      • 以非事务的方式执行操作,如果当前存在事务,则将其挂起。

    6. PROPAGATION_NEVER:

      • 以非事务方式执行操作,如果当前存在事务,则抛出异常。

    7. PROPAGATION_NESTED:

      • 如果当前存在事务,则创建一个嵌套事务,并且它是当前事务的一个保存点(savepoint)。如果不存在事务,则行为类似于PROPAGATION_REQUIRED

  6. 事务隔离级别: 事务隔离级别定义了在多个事务同时执行时,一个事务对数据的修改对其他事务的可见性程度。Spring定义了五个事务隔离级别,每个级别都有不同的特性和影响:

    1. READ_UNCOMMITTED(读取未提交):

      • 特性:允许一个事务读取另一个事务未提交的数据。

      • 可能问题:脏读、不可重复读、幻读。

    2. READ_COMMITTED(读取已提交):

      • 特性:一个事务只能读取已经提交的另一个事务的数据。

      • 可能问题:不可重复读、幻读。

    3. REPEATABLE_READ(可重复读):

      • 特性:确保事务可以多次从相同的数据集读取相同的数据,即使其他事务正在修改这些数据。

      • 可能问题:幻读。

    4. SERIALIZABLE(序列化):

      • 特性:事务是串行执行的,所有的事务都按顺序依次执行,不允许并发执行。

      • 可能问题:性能较低,但避免了脏读、不可重复读、幻读。

    5. DEFAULT:

      • 使用数据库默认的隔离级别,通常是数据库的默认配置。

  7. 事务回滚规则: Spring允许你配置哪些异常触发事务回滚,哪些异常不触发事务回滚。

  8. 分布式事务: Spring提供对分布式事务的支持,通过 JtaTransactionManager 实现了对JTA事务的集成。

PlatformTransactionManager概述

Spring的事务管理模块定义了一个平台事务管理器(PlatformTransactionManager)接口,该接口有多种实现,以适应不同的事务管理机制。主要的实现类包括:

  1. DataSourceTransactionManager: 用于基于JDBC的事务管理,适用于关系型数据库,如MySQL、PostgreSQL等。

  2. HibernateTransactionManager: 用于基于Hibernate的事务管理,适用于使用Hibernate框架的应用。

  3. JtaTransactionManager: 用于基于Java EE的JTA(Java Transaction API)事务管理,适用于复杂的分布式事务场景。

  4. JpaTransactionManager: 用于基于JPA(Java Persistence API)的事务管理,适用于使用JPA的应用。

  5. WebLogicJtaTransactionManager: 专门用于WebLogic服务器上的JTA事务管理。

实体类domain层

package domain;
​
public class account {private String name;private int gold;
​public account(String name, int gold) {this.name = name;this.gold = gold;}
​public account() {}
​public String getName() {return name;}
​public void setName(String name) {this.name = name;}
​public int getGold() {return gold;}
​public void setGold(int gold) {this.gold = gold;}
​@Overridepublic String toString() {return "account{" +"name='" + name + '\'' +", gold=" + gold +'}';}
}
​

Dao层

接口

package dao;
​
public interface accountDao {public void out(String man,int money);转出public void in(String man,int money);转入
​
​
}
​

实现类

package dao.Impl;
​
import dao.accountDao;
import org.springframework.jdbc.core.JdbcTemplate;
​
public class accountImpl implements accountDao {JdbcTemplate jdbcTemplate ;
​
•    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
•        this.jdbcTemplate = jdbcTemplate;
•    }
​
•    @Override
•    public void out(String man, int money) {
•        jdbcTemplate.update("update account set gold=gold-? where name=?",money,man);
•    }
​
•    @Override
•    public void in(String man,int money) {
•        jdbcTemplate.update("update account set gold=gold+? where name=?",money,man);
•    }
​
​
}

service层

接口

package dao;
​
public interface accountDao {public void out(String man,int money);public void in(String man,int money);
​
​
}
​

实现类

package service.Impl;
​
import dao.accountDao;
import service.accountService;
​
public class accountServiceImpl implements accountService {
​accountDao  accountdao;
​public void setAccountdao(accountDao accountdao) {this.accountdao = accountdao;}
​@Overridepublic void transfer(String outman, String inman, int money) {accountdao.out(outman,money);int i=1/0;accountdao.in(inman,money);}
}

ApplicationContext.xml配置

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><context:property-placeholder location="classpath:mysql.properties"></context:property-placeholder>配置数据源<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.Driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.user}"></property><property name="password" value="${jdbc.password}"></property></bean>配置jdbc模板<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="datasource"></property></bean><bean id="account" class="dao.Impl.accountImpl"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean><bean id="accountService" class="service.Impl.accountServiceImpl"><property name="accountdao" ref="account"></property></bean>
<!--    配置事务管理平台-->
这里是基于springjdbc模板实现的所以用的是DataSource<bean id="transaction"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="datasource"></property></bean>
<!--    通知--><tx:advice id="myAdvice" transaction-manager="transaction"><tx:attributes>
<!--            哪些方法被增强--><tx:method name="transfer"isolation="READ_COMMITTED"propagation="REQUIRED" read-only="false"   因为转账肯定需要修改 所以不是只读/></tx:attributes></tx:advice>
<!--    配置事务的aop织入--><aop:config><aop:advisor advice-ref="myAdvice"pointcut="execution(* service.Impl.accountServiceImpl.*(..))"/></aop:config>
</beans>

注解式声明式事务管理

xml配置

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><context:property-placeholder location="classpath:mysql.properties"></context:property-placeholder>配置数据源<bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.Driver}"></property><property name="jdbcUrl" value="${jdbc.url}"></property><property name="user" value="${jdbc.user}"></property><property name="password" value="${jdbc.password}"></property></bean>配置jdbc模板<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="datasource"></property></bean><bean id="account" class="dao.Impl.accountImpl"><property name="jdbcTemplate" ref="jdbcTemplate"></property></bean><bean id="accountService" class="service.Impl.accountServiceImpl"><property name="accountdao" ref="account"></property></bean>
<!--    配置事务管理平台-->
这里是基于springjdbc模板实现的所以用的是DataSource<bean id="transaction"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="datasource"></property></bean>新加<tx:annotation-driven transaction-manager="transaction"></tx:annotation-driven><context:component-scan base-package="org.dao.Impl" /><context:component-scan base-package="org.service.Impl" />组件扫描<aop:aspectj-autoproxy></aop:aspectj-autoproxy>    启用 AspectJ 自动代理<context:annotation-config></context:annotation-config>启用注解驱动的配置,包括支持注解驱动的 AOP。在这个上下文中,主要是为了支持 @Transactional 注解,它用于启用声明式事务管理。在这个配置中,它会启用对带有 @Repository, @Service, @Controller 和其他注解的类的处理,以及其他一些注解相关的功能。

@Transactional() 等价于

<!-- 通知--> <tx:advice id="myAdvice" transaction-manager="transaction"> tx:attributes <!-- 哪些方法被增强--> <tx:method name="transfer" isolation="READ_COMMITTED" propagation="REQUIRED" read-only="false" 因为转账肯定需要修改 所以不是只读 /> /tx:attributes /tx:advice <!-- 配置事务的aop织入--> aop:config <aop:advisor advice-ref="myAdvice" pointcut="execution(* service.Impl.accountServiceImpl.*(..))"/> /aop:config </beans>

总结

转账这个例子 就是主动设计的错误是脏读 如果转账时出现网络 错误 一方转出了钱 ,一方没有收到钱,此时是不合理的,所以需要事务管理

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

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

相关文章

Kotlin学习——kt里的集合List,Set,Map List集合的各种方法之Int篇

Kotlin 是一门现代但已成熟的编程语言&#xff0c;旨在让开发人员更幸福快乐。 它简洁、安全、可与 Java 及其他语言互操作&#xff0c;并提供了多种方式在多个平台间复用代码&#xff0c;以实现高效编程。 https://play.kotlinlang.org/byExample/01_introduction/02_Functio…

Win10/Win11 使用Wsl的Ubuntu 子系统搭建CGO环境,相当于Ubuntu下开发。GO环境CGO搭建,支持交叉编译

背景&#xff1a; 之前是使用Mac 开发&#xff0c;最近切换到win11下面。发现使用cgo编译有问题。 下面记载了我的使用方法。 环境&#xff1a; win11&#xff08;win10理论一样&#xff09; win11 安装了wsl2的环境&#xff0c;并且安装了ubuntu系统。 在win11 上面安装了g…

vue3(二)-基础入门

一、列表渲染 of 和 in 都是一样的效果 html代码&#xff1a; <div id"app"><ul><li v-for"item of datalist">{{ item }}</li></ul><ul><li v-for"item in dataobj">{{ item }}</li></u…

Flask,uWSGI,nginx的理解

文章目录 前言与背景理解 - FlaskuWSGInginx理解 - nginx理解 - FlaskuWSGI理解 - vuedjangonginx 前言与背景 此篇文章是针对小白的一篇理解Flask&#xff0c;uWSGI&#xff0c;nginx的文章&#xff0c;只介绍了理解&#xff0c;并没有介绍如何部署。 由于工作需要使用flask…

npm pnpm yarn(包管理器)的安装及镜像切换

安装Node.js 要安装npm&#xff0c;你需要先安装Node.js。 从Node.js官方网站&#xff08;https://nodejs.org&#xff09;下载并安装Node.js。 根据你的需要选择相应的版本。 一路Next&#xff0c;直到Finish 打开CMD&#xff0c;输入命令来检查Node.js和npm是否成功安装 nod…

Gin 学习笔记02-参数获取

Gin 参数获取 1、获取url 参数2、获取动态 url 参数3、获取 form 表单数据 1、获取url 参数 Query()GetQuery()QueryMap()DefaultQuery() package mainimport ("fmt""github.com/gin-gonic/gin""net/http" )func _query(c *gin.Context) {// 1…

Docker Swarm总结+基础、集群搭建维护、安全以及集群容灾(1/4)

博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码下载地址&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb;…

【WSA】无法打开 适用于 Android™ 的 Windows 子系统,因为它处于脱机状态。可能缺少存储设备,或者存储设备已断开连接。

问题描述 之前可以正常使用适用于 Android™ 的 Windows 子系统&#xff08;WSA&#xff09;&#xff0c;但突然间无法启动了。 当尝试启动WSA中的软件时&#xff0c;都会出现以下错误提示&#xff1a; 无法打开 适用于 Android™ 的 Windows 子系统&#xff0c;因为它处于脱…

chrome driver 截图和填表

昨天突然有一个需求&#xff08;自己的&#xff09;&#xff0c;想把某个网站题目主体部分翻译并保存成图片&#xff0c;开始时用了国内网站的翻译&#xff08;人工、简单翻译&#xff09;&#xff0c;后来发现很多地方翻译的不尽人意&#xff0c;于是只好用翻译插件对原始网站…

2311skia,04绘制路径

分析Skia绘画路径代码 绘画路径尽管使用频率相对绘画图像,绘画文本低,但却是非常重要的一个基本特性.所有不规则图形(椭圆,圆角矩形,三角形,简单的文字),最后都要绘画路径. 而且,若自己实现一个2D引擎,这块内容是很有参考意义的,用OpenGL,都很少关注采样图像了,对对坐标就好. …

cjson库打包数据实现方法

使用 cJson 库&#xff0c;在C语言环境下&#xff0c;打包一个cJson字符串&#xff1a; int CreateArryJsonString(void) {cJSON *cJsonArr cJSON_CreateArray();cJSON *sJsonObj1 cJSON_CreateObject();cJSON_AddStringToObject(sJsonObj1, "test1", "test1…

动态规划学习——子序列问题

目录 ​编辑 一&#xff0c;最长定差子序列 1.题目 2&#xff0c;题目接口 3&#xff0c;解题思路及其代码 一&#xff0c;最长定差子序列 1.题目 给你一个整数数组 arr 和一个整数 difference&#xff0c;请你找出并返回 arr 中最长等差子序列的长度&#xff0c;该子序列…

机器学习【03】在本地浏览器使用远程服务器的Jupyter Notebook【conda环境】

1.激活虚拟环境 conda activate 虚拟环境名字2.虚拟环境下安装jupyter notebook pip install jupyter3.配置 jupyter 文件 在 Jupyter Notebook 的配置目录中生成一个配置文件 jupyter_notebook_config.py jupyter notebook --generate-config3.设置密码 jupyter notebook …

C/C++ 常用加密与解密算法

计算机安全和数据隐私是现代应用程序设计中至关重要的方面。为了确保数据的机密性和完整性&#xff0c;常常需要使用加密和解密算法。C是一种广泛使用的编程语言&#xff0c;提供了许多加密和解密算法的实现。本文将介绍一些在C中常用的加密与解密算法&#xff0c;这其中包括Xo…

[vxe-table] vxe-table-column配合v-if导致列样式与位置错乱

<vxe-table-column v-if"pageInfo.id 4 ||pageInfo.id 8" title"上报类型" width"100" key1><template v-slot"{row}"><span>咨询工具</span></template> </vxe-table-column>//或者<vxe-ta…

操作NAND flash W25N01G

文章目录 W25N01G1 描述2 特点3 封装3.3.2 连接线 4 引脚/CSDO/WP/Hold SPI指令标准SPI命令双SPI四元SPI命令写保护 5 地址PA与PC最后一个扇区 OTP寄存器1块保护清除块保护指令* WP-E 寄存器2寄存器3BUSYP-FAILE-FAILECC位 8 命令8.1 装置ID 指令解读写状态寄存器 注意内容上拉…

Java,File类与IO流,处理流:缓冲流、转换流、数据流、对象流

目录 处理流之一&#xff1a;缓冲流 四种缓冲流&#xff1a; 缓冲流的作用&#xff1a; 使用的方法&#xff1a; 处理文本文件的字符流&#xff1a; 处理非文本文件的字节流&#xff1a; 操作步骤&#xff1a; 处理流之二&#xff1a;转换流 转换流的使用&#xff1a; …

企业编码生成程序Python毕业设计

&#xff08;1&#xff09;生成6位数字防伪编码。当用户在主程序界面中输入数字“1”菜单项时&#xff0c;将进入“生成6位数字防伪编码 &#xff08;213563型&#xff09;”的功能执行任务。此时要求输入生成防伪码的数量&#xff0c;可以根据需要输入生成防伪码的数量。按下&…

范围查询 range级别 继续优化思路

问题&#xff1a; 这几天工作遇到了一个问题。千万级别的表&#xff0c;每秒钟产生很多数据&#xff0c;select count(id) from table where flag 1 and create_time < 2023.11.07;分区表&#xff0c;range级别&#xff0c;已经是走create_time列上的索引&#xff0c;flag…