百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Spring事务与传播行为(spring事务传播行为包括哪些)

bigegpt 2024-08-01 12:02 8 浏览

课程目标:

Spring事务概念、理解事务的传播行为

一、事务的概述

⑴ 原子性(Atomicity)

原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

⑵ 一致性(Consistency)

一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。

⑶ 隔离性(Isolation)

隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。

关于事务的隔离性数据库提供了多种隔离级别,稍后会介绍到。

⑷ 持久性(Durability)

持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

例如我们在使用JDBC操作数据库时,在提交事务方法后,提示用户事务操作完成,当我们程序执行完成直到看到提示后,就可以认定事务以及正确提交,即使这时候数据库出现了问题,也必须要将我们的事务完全执行完成,否则就会造成我们看到提示事务处理完毕,但是数据库因为故障而没有执行事务的重大错误。

二、程序中事务控制

2.1 环境准备

用户访问—》C–》 Service—》Dao

一个业务的成功: 调用的service是执行成功的,意味着service中调用的所有的dao是执行成功的。 事务应该在Service层统一控制。

1)没有应用事务的代码:

2)模拟:

在service中调用2次dao, 希望其中一个dao执行失败,整个操作要回滚。

开发步骤:

1. 后台环境准备

数据库、表/entity/dao/service

2. dao 的实现用JdbcTemplate

3. 对象创建都有Spring容器完成

三、程序中事务控制

3.1事务控制概述

编程式事务控制

自己手动控制事务,就叫做编程式事务控制。

Jdbc代码:

Conn.setAutoCommite(false); // 设置手动控制事务

Hibernate代码:

Session.beginTransaction(); // 开启一个事务

【细粒度的事务控制: 可以对指定的方法、指定的方法的某几行添加事务控制】

(比较灵活,但开发起来比较繁琐: 每次都要开启、提交、回滚.)

声明式事务控制

Spring提供了对事务的管理, 这个就叫声明式事务管理。

Spring提供了对事务控制的实现。用户如果想用Spring的声明式事务管理,只需要在配置文件中配置即可; 不想使用时直接移除配置。这个实现了对事务控制的最大程度的解耦。

Spring声明式事务管理,核心实现就是基于Aop。

【粗粒度的事务控制: 只能给整个方法应用事务,不可以对方法的某几行应用事务。】

(因为aop拦截的是方法。)

Spring声明式事务管理器类:
	Jdbc技术:DataSourceTransactionManager
	Hibernate技术:HibernateTransactionManager

3.2编程事物管理

3.2.1手动管理事物

1. UserDao.java
@Repository
public class UserDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;
	public void add(String name, Integer age) {
		String sql = "INSERT INTO users(NAME, age) VALUES(?,?);";
		int update = jdbcTemplate.update(sql, name, age);
		System.out.println("updateResult:" + update);
	}
}
2. UserService
@Service
public class UserService {
	@Autowired
	private UserDao userDao;
	public void add() {
		userDao.add("lisi", 18);
		int i=1/0;//可能会发生异常
		userDao.add("yushengjun", 19);
	}
}
3. App 测试类
public class UserTest {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.add();
	}
}
4.手动事物管理类
@Component
public class TransactionUtils {
	// 事物管理器
	@Autowired
	private DataSourceTransactionManager dataSourceTransactionManager;
	public TransactionStatus begin() {
		TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
		return transaction;
	}
	public void commit(TransactionStatus transaction) {
		dataSourceTransactionManager.commit(transaction);
	}
	public void rollback(TransactionStatus transaction) {
		dataSourceTransactionManager.rollback(transaction);
	}
}
5. bean.xml (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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
 	 http://www.springframework.org/schema/beans/spring-beans.xsd
 	 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop.xsd
 http://www.springframework.org/schema/tx
 	 http://www.springframework.org/schema/tx/spring-tx.xsd">
	<!-- 开启注解 -->
	<context:component-scan base-package="com.itmayiedu"></context:component-scan>
	<!-- 1. 数据源对象: C3P0连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
		<property name="user" value="root"></property>
		<property name="password" value="root"></property>
	</bean>
	<!-- 2. JdbcTemplate工具类实例 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
 <!-- 配置事物 -->
 <bean id="DataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
 <property name="dataSource" ref="dataSource"></property>
 </bean>
</beans> 

3.3声明式事务管理

3.3.1 XML方式实现

1. UserDao.java
@Repository
public class UserDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;
	public void add(String name, Integer age) {
		String sql = "INSERT INTO users(NAME, age) VALUES(?,?);";
		int update = jdbcTemplate.update(sql, name, age);
		System.out.println("updateResult:" + update);
	}
}
2. UserService
@Service
public class UserService {
	@Autowired
	private UserDao userDao;
	public void add() {
		userDao.add("lisi", 18);
		int i=1/0;//可能会发生异常
		userDao.add("yushengjun", 19);
	}
}
3. App 测试类
public class UserTest {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("bean.xml");
		UserService userService = (UserService) applicationContext.getBean("userService");
		userService.add();
	}
}
4.手动事物管理类
@Component
public class TransactionUtils {
	// 事物管理器
	@Autowired
	private DataSourceTransactionManager dataSourceTransactionManager;
	public TransactionStatus begin() {
		TransactionStatus transaction = dataSourceTransactionManager.getTransaction(new DefaultTransactionDefinition());
		return transaction;
	}
	public void commit(TransactionStatus transaction) {
		dataSourceTransactionManager.commit(transaction);
	}
	public void rollback(TransactionStatus transaction) {
		dataSourceTransactionManager.rollback(transaction);
	}
}
5. bean.xml (Spring务管理配置)
	<!-- 开启注解 -->
	<context:component-scan base-package="com.itmayiedu"></context:component-scan>
	<!-- 1. 数据源对象: C3P0连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
		<property name="user" value="root"></property>
		<property name="password" value="root"></property>
	</bean>
	<!-- 2. JdbcTemplate工具类实例 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 配置事物 -->
	<bean id="dataSourceTransactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
 	<!—配置事物增强-->
	<tx:advice id="txAdvice" transaction-manager="dataSourceTransactionManager">
		<tx:attributes>
			<tx:method name="get*" read-only="true" />
			<tx:method name="find*" read-only="true" />
			<tx:method name="*" read-only="false" />
		</tx:attributes>
	</tx:advice>
	<!-- Aop配置: 拦截哪些方法(切入点表表达式) + 应用上面的事务增强配置 -->
	<aop:config>
		<aop:pointcut expression="execution(* com.itmayiedu.service.*.*(..))"
			id="pt" />
		<aop:advisor advice-ref="txAdvice" pointcut-ref="pt" />
	</aop:config>

使用事物注意事项

事物是程序运行如果没有错误,会自动提交事物,如果程序运行发生异常,则会自动回滚。

如果使用了try捕获异常时.一定要在catch里面手动回滚。

事物手动回滚代码

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

3.3.2 注解方式实现

使用注解实现Spring的声明式事务管理,更加简单!

步骤:

1) 必须引入Aop相关的jar文件

2) bean.xml中指定注解方式实现声明式事务管理以及应用的事务管理器类

3)在需要添加事务控制的地方,写上: @Transactional

@Transactional注解:

1)应用事务的注解

2)定义到方法上: 当前方法应用spring的声明式事务

3)定义到类上: 当前类的所有的方法都应用Spring声明式事务管理;

4)定义到父类上: 当执行父类的方法时候应用事务。

Bean.xm
<?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:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
 	 http://www.springframework.org/schema/beans/spring-beans.xsd
 	 http://www.springframework.org/schema/context
 http://www.springframework.org/schema/context/spring-context.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop.xsd
 http://www.springframework.org/schema/tx
 	 http://www.springframework.org/schema/tx/spring-tx.xsd">
	<!-- 开启注解 -->
	<context:component-scan base-package="com.itmayiedu"></context:component-scan>
	<!-- 1. 数据源对象: C3P0连接池 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
		<property name="user" value="root"></property>
		<property name="password" value="root"></property>
	</bean>
	<!-- 2. JdbcTemplate工具类实例 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 配置事物 -->
	<bean id="dataSourceTransactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	<!-- 开启注解事物 -->
 <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
</beans> 
UserService
@Transactional
	public void add() {
		try {
			userDao.add("lisi", 18);
			int i = 1 / 0;
			userDao.add("yushengjun", 19);
		} catch (Exception e) {
			TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
		}
		
	}

四、传播七种行为

Spring中事务的定义:

Propagation(key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。)有以下选项可供使用:

?PROPAGATION_REQUIRED–支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

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

?PROPAGATION_MANDATORY–支持当前事务,如果当前没有事务,就抛出异常。

?PROPAGATION_REQUIRES_NEW–新建事务,如果当前存在事务,把当前事务挂起。

?PROPAGATION_NOT_SUPPORTED–以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

?PROPAGATION_NEVER–以非事务方式执行,如果当前存在事务,则抛出异常。

@Transactional(

readOnly = false, // 读写事务

timeout = -1, // 事务的超时时间不限制

noRollbackFor = ArithmeticException.class, // 遇到数学异常不回滚

isolation = Isolation.DEFAULT, // 事务的隔离级别,数据库的默认

propagation = Propagation.REQUIRED// 事务的传播行为

)

事务传播行为:

Propagation.REQUIRED

指定当前的方法必须在事务的环境下执行;

如果当前运行的方法,已经存在事务, 就会加入当前的事务;

Propagation.REQUIRED_NEW

指定当前的方法必须在事务的环境下执行;

如果当前运行的方法,已经存在事务: 事务会挂起; 会始终开启一个新的事务,执行完后; 刚才挂起的事务才继续运行。

举例:

Class Log{
		Propagation.REQUIRED 
		insertLog(); 
}
	Propagation.REQUIRED
	Void saveDept(){
		insertLog(); // 加入当前事务
		.. 异常, 会回滚
		saveDept();
	}
	Class Log{
		Propagation.REQUIRED_NEW 
		insertLog(); 
}
	Propagation.REQUIRED
	Void saveDept(){
		insertLog(); // 始终开启事务
		.. 异常, 日志不会回滚
		saveDept();
	}

测试步骤:

1)日志表Log_

2)LogService.java

insertLog();

相关推荐

得物可观测平台架构升级:基于GreptimeDB的全新监控体系实践

一、摘要在前端可观测分析场景中,需要实时观测并处理多地、多环境的运行情况,以保障Web应用和移动端的可用性与性能。传统方案往往依赖代理Agent→消息队列→流计算引擎→OLAP存储...

warm-flow新春版:网关直连和流程图重构

本期主要解决了网关直连和流程图重构,可以自此之后可支持各种复杂的网关混合、多网关直连使用。-新增Ruoyi-Vue-Plus优秀开源集成案例更新日志[feat]导入、导出和保存等新增json格式支持...

扣子空间体验报告

在数字化时代,智能工具的应用正不断拓展到我们工作和生活的各个角落。从任务规划到项目执行,再到任务管理,作者深入探讨了这款工具在不同场景下的表现和潜力。通过具体的应用实例,文章展示了扣子空间如何帮助用户...

spider-flow:开源的可视化方式定义爬虫方案

spider-flow简介spider-flow是一个爬虫平台,以可视化推拽方式定义爬取流程,无需代码即可实现一个爬虫服务。spider-flow特性支持css选择器、正则提取支持JSON/XML格式...

solon-flow 你好世界!

solon-flow是一个基础级的流处理引擎(可用于业务规则、决策处理、计算编排、流程审批等......)。提供有“开放式”驱动定制支持,像jdbc有mysql或pgsql等驱动,可...

新一代开源爬虫平台:SpiderFlow

SpiderFlow:新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。-精选真开源,释放新价值。概览Spider-Flow是一个开源的、面向所有用户的Web端爬虫构建平台,它使用Ja...

通过 SQL 训练机器学习模型的引擎

关注薪资待遇的同学应该知道,机器学习相关的岗位工资普遍偏高啊。同时随着各种通用机器学习框架的出现,机器学习的门槛也在逐渐降低,训练一个简单的机器学习模型变得不那么难。但是不得不承认对于一些数据相关的工...

鼠须管输入法rime for Mac

鼠须管输入法forMac是一款十分新颖的跨平台输入法软件,全名是中州韵输入法引擎,鼠须管输入法mac版不仅仅是一个输入法,而是一个输入法算法框架。Rime的基础架构十分精良,一套算法支持了拼音、...

Go语言 1.20 版本正式发布:新版详细介绍

Go1.20简介最新的Go版本1.20在Go1.19发布六个月后发布。它的大部分更改都在工具链、运行时和库的实现中。一如既往,该版本保持了Go1的兼容性承诺。我们期望几乎所...

iOS 10平台SpriteKit新特性之Tile Maps(上)

简介苹果公司在WWDC2016大会上向人们展示了一大批新的好东西。其中之一就是SpriteKitTileEditor。这款工具易于上手,而且看起来速度特别快。在本教程中,你将了解关于TileE...

程序员简历例句—范例Java、Python、C++模板

个人简介通用简介:有良好的代码风格,通过添加注释提高代码可读性,注重代码质量,研读过XXX,XXX等多个开源项目源码从而学习增强代码的健壮性与扩展性。具备良好的代码编程习惯及文档编写能力,参与多个高...

Telerik UI for iOS Q3 2015正式发布

近日,TelerikUIforiOS正式发布了Q32015。新版本新增对XCode7、Swift2.0和iOS9的支持,同时还新增了对数轴、不连续的日期时间轴等;改进TKDataPoin...

ios使用ijkplayer+nginx进行视频直播

上两节,我们讲到使用nginx和ngixn的rtmp模块搭建直播的服务器,接着我们讲解了在Android使用ijkplayer来作为我们的视频直播播放器,整个过程中,需要注意的就是ijlplayer编...

IOS技术分享|iOS快速生成开发文档(一)

前言对于开发人员而言,文档的作用不言而喻。文档不仅可以提高软件开发效率,还能便于以后的软件开发、使用和维护。本文主要讲述Objective-C快速生成开发文档工具appledoc。简介apple...

macOS下配置VS Code C++开发环境

本文介绍在苹果macOS操作系统下,配置VisualStudioCode的C/C++开发环境的过程,本环境使用Clang/LLVM编译器和调试器。一、前置条件本文默认前置条件是,您的开发设备已...