05-Spring-事务管理
2022/9/12 23:23:08
本文主要是介绍05-Spring-事务管理,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1.事务管理
-
概念:
事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,要么都失败,
如果有一个失败操作那么所有的操作都失败
-
事务四个特性(ACID)
-
原子性(Atomicity):
指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
-
一致性(Consistency):
事务前后数据的完整性必须保持一致。
-
隔离性(Isolation):
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
-
持久性(Durability):
持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响
事务的运行
- 开启事务
- 进行业务操作
- 没有发生异常,提交事务
- 发生异常,进行事务回滚
2.声明式事务管理
2.1 实现步骤
-
创建配置事务管理器
DataSourceTransactionManage (针对JdbcTemplate或Mybatis)
-
开启事务
@EnableTransactionManagement 或者配置 < tx:annotation-driven/>
-
在需要进行事务处理的类或者方法上添加事务注解
@Transactional
(1)基于注解实现
配置类:SpringConfig.java
@Configuration @ComponentScan(basePackages = {"com.potato"}) @EnableTransactionManagement // 2.开启事务注解 public class SpringConfig { //1.创建配置事务管理器 DataSourceTransactionManager @Bean(name = "transactionManager") public DataSourceTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } @Bean(name = "dataSource") public DataSource createDataSource() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/spring5"); dataSource.setUsername("root"); dataSource.setPassword("root"); return dataSource; } @Bean(name = "jdbcTemplate") public JdbcTemplate createDataSource(DataSource dataSource) { JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); return jdbcTemplate; } }
需要事务处理的类:BankServiceImpl.java
//3.在需要进行事务处理的类或者方法上添加事务注解 @Transactional @Override public Integer transferAccounts(String saveAccount, String takeAccount, int money) { Integer take = bankDao.take(takeAccount, money); Integer save = bankDao.save(saveAccount, money); return take == save ? (take != 0 ? 1 : 0) : 0; }
(2)基于xml配置文件实现
配置文件
<context:component-scan base-package="com.potato"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="com.driver.jdbc.mysql"/> <property name="url" value="jdbc:mysql://127.0.0.1:3306/spring5"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg ref="dataSource"/> </bean> <!-- 1.创建事务管理器--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 2.开启事务注解--> <tx:annotation-driven transaction-manager="transactionManager"/>
2.2 Spring事务管理API :PlatformTransactionManager接口
PlatformTransactionManager:事务管理的接口,有多个不同的实现类分别针对不同的数据处理框架
DataSourceTransactionManager :JdbcTemplate、Mybatis
HibernateTransactionManager:Hibernate
2.3 @Transactional 相关参数
propagation:事务传播行为
isolation:事务隔离级别
timeout:超时时间
readOnly:是否只读
rollbackFor:发生指定的异常则回滚
noRollbackFor:发生指定的异常则不回滚
2.4 传播行为:propagation
传播属性 | 解析 |
---|---|
REQUIRED(默认) | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中, 就继续使用该事务。这是最常见的选择。 |
REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
MANDATORY | 使用当前的事务,如果当前没有事务,就抛出异常。 |
NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
NESTED | 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务, 则执行与REQUIRED类似的操作。 |
2.5 隔离级别:isolation
-
不考虑隔离性 则会产生以下三个问题
-
脏读:
在多事务之间:一个未提交的事务读取到另一个未提交事务的数据
-
不可重复读
两个事务,事务A与事务B,事务A在自己执行的过程中,执行了两次相同查询,
第一次查询事务时B未提交,第二次查询事务时B已提交,从而造成两次查询结果不一样
-
幻读(虚读)
在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
-
-
隔离级别参数
属性值 脏读 不可重复读 幻读 READ_UNCOMMITTED(读未提交) 有 有 有 READ_COMMITTED(读以提交) 无 有 有 REPEATABLE_READ(可重复读) (默认) 无 无 有 SERIALIZABLE(串行化) 无 无 无
2.6 其他参数
-
timeout:超时时间 秒为单位
事务在一定时间内进行提交,如果不提交则进行回滚
-
readOnly:是否只读
(1)1.读:查询操作 2.写:增删改操作
(2)默认值为 false, 表示可以增删改查
(3)设置为true 则是只读操作
-
rollbackFor:回滚
(1)设置出现哪些异常需要进行事务回滚
-
noRollbackFor:不回滚
(1)设置出现哪些异常不需要进行事务回滚
3.编程式事务管理
-
实现步骤
1.配置事务管理器
2.配置通知
3.配置切入点和切面
spring-config.xml
<context:property-placeholder location="druid.properties"/> <context:component-scan base-package="com.potato"/> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driverClass}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <constructor-arg ref="dataSource"/> </bean> <!-- 1 创建事务管理器--> <bean id="transactionManager2" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 2 配置通知--> <tx:advice id="txAdvice"> <!-- 2.1 配置事务参数--> <tx:attributes> <!-- 2.2 指定哪种方法上添加事务 名字以transfer开头的方法添加事务--> <tx:method name="transfer*" propagation="REQUIRED"/> </tx:attributes> </tx:advice> <!-- 3 配置切面--> <aop:config> <!-- 3.1 配置切入点--> <aop:pointcut id="pointcut01" expression="execution(* com.potato.service.BankService.*(..))"/> <!-- 3.2 配置切面--> <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut01"/> </aop:config>
这篇关于05-Spring-事务管理的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-04-26敏捷开发:想要快速交付就必须舍弃产品质量?
- 2024-04-26静态代码分析的这些好处,我竟然都不知道?
- 2024-04-26你在测试金字塔的哪一层?(下)
- 2024-04-26快刀斩乱麻,DevOps让代码评审也自动起来
- 2024-04-262024年最好用的10款ER图神器!
- 2024-04-2203-为啥大模型LLM还没能完全替代你?
- 2024-04-2101-大语言模型发展
- 2024-04-17基于SpringWeb MultipartFile文件上传、下载功能
- 2024-04-14个人开发者,Spring Boot 项目如何部署
- 2024-04-14RAG应用开发实战02-相似性检索的关键 - Embedding