Spring 框架基础(05):事务管理机制,和实现方式
本文源码:GitHub·点这里 || GitEE·点这里
一、Spring事务管理
1、基础描述
Spring
事务管理的本质就是封装了数据库对事务支持的操作,使用JDBC的事务管理机制,就是利用java.sql.Connection
对象完成对事务的提交和回滚。
Connection conn = DriverManager.getConnection(); try { // 自动提交设置为false conn.setAutoCommit(false); // 执行增删改查操作 // 当操作成功后手动提交 conn.commit(); } catch (Exception e) { // 出现异常,回滚所有操作 conn.rollback(); e.printStackTrace(); } finally { conn.colse(); }
2、事务常见概念
- 事务
事务是指作为单个逻辑工作单元执行的一系列操作(SQL语句)。这些操作要么全部成功,要么全部不成功。
- 特性:ACID
原子性(Atomicity):事务中的多个操作要么都成功要么都失败 一致性(consistency):事务的执行的前后数据的完整性保持一致 隔离性(isolation):事务执行的过程中,不应该受到其他事务的干扰 持久性(durability):事务一旦结束,数据就持久到数据库
- 隔离问题
脏读:一个事务读到另一个事务没有提交的数据
不可重复读:一个事务前后多次读取相同数据,数据内容不一致,update场景问题
虚读(幻读):一个事务前后多次读取,数据总量不一致,insert场景问题
- 隔离级别
read uncommitted
:
事务可以读取另一个未提交事务的数据。
read committed
:
事务要等另一个事务提交后才能读取数据,解决脏读。
repeatable read
:
在开始读取数据时,事务开启,不再允许修改操作,解决:脏读、不可重复读。
serializable
:
最高事务隔离级别,事务串行化顺序执行,解决脏读、不可重复读、幻读。但是效率低下,耗数据库性能。
3、事务管理API描述
PlatformTransactionManager
平台事务管理器,Spring管理事务,必须使用事务管理器进行事务配置时,核心方法:获取事务,提交事务,回滚事务。
TransactionDefinition
该对象封装事务详情(事务定义、事务属性),例如:隔离级别、是否只读、超时时间 等。
TransactionStatus
用于记录当前事务运行状态。例如:是否有保存点,事务是否完成。Spring底层根据状态进行相应操作。
4、事务案例SQL语句
CREATE TABLE user_account( id INT PRIMARY KEY AUTO_INCREMENT, username VARCHAR(50), money INT ) ENGINE=InnoDB DEFAULT CHARSET=utf8;; INSERT INTO user_account(username,money) VALUES('jack','5000'); INSERT INTO user_account(username,money) VALUES('tom','5000'); SELECT * FROM user_account ;
二、编程式事务管理
1、核心配置文件
<!-- 配置事物管理器 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 创建事物模板 --> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="txManager" /> </bean> <!-- 配置转账接口 --> <bean id="userAccountService" class="com.spring.mvc.service.impl.UserAccountServiceImpl"> <property name="jdbcTemplate" ref="jdbcTemplate" /> <property name="transactionTemplate" ref="transactionTemplate" /> </bean>
2、演示案例
@Service public class UserAccountServiceImpl extends JdbcDaoSupport implements UserAccountService { // 注入事物模板 private TransactionTemplate transactionTemplate ; public void setTransactionTemplate(TransactionTemplate transactionTemplate) { this.transactionTemplate = transactionTemplate; } @Override public void remittance(String remitTer, String receiver, int money) { transactionTemplate.execute(new TransactionCallbackWithoutResult() { public void doInTransactionWithoutResult(TransactionStatus arg0) { outMoney(remitTer,money); // System.out.println(1/0); innerMoney(receiver,money); } }); } private void outMoney (String remitTer, int money){ String outSql = "update user_account set money = money - ? where username = ?"; this.getJdbcTemplate().update(outSql, money ,remitTer); } private void innerMoney (String receiver, int money){ String inSql = "update user_account set money = money + ? where username = ?"; this.getJdbcTemplate().update(inSql, money,receiver); } }
三、事务代理工厂
1、核心配置
<!-- 配置转账接口 --> <bean id="userAccountService01" class="com.spring.mvc.service.impl.UserAccountServiceImpl01"> <property name="jdbcTemplate" ref="jdbcTemplate" /> </bean> <!-- 配置事务代理工厂 --> <bean id="proxyAccountService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="proxyInterfaces" value="com.spring.mvc.service.UserAccountService01" /> <property name="target" ref="userAccountService01" /> <property name="transactionManager" ref="txManager" /> <property name="transactionAttributes"> <props> <!-- 默认传播行为、隔离级别 --> <prop key="remittance">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop> <!-- 异常仍然提交事务 <prop key="remittance">PROPAGATION_REQUIRED,ISOLATION_DEFAULT,+java.lang.Exception</prop> --> </props> </property> </bean>
配置说明:
-
proxyInterfaces
代理接口 -
target
代理目标类 -
transactionManager
事务管理器 -
transactionAttributes
事务属性(事务详情) -
prop.key
指定方法使用当前事务配置
事务行为:
-
PROPAGATION
传播行为 -
ISOLATION
隔离级别 -
readOnly
是否只读 -
-Exception
异常回滚 -
+Exception
异常提交
2、演示案例
@Service public class UserAccountServiceImpl01 extends JdbcDaoSupport implements UserAccountService01 { @Override public void remittance(String remitTer, String receiver, int money) { outMoney(remitTer,money); System.out.println(1/0); innerMoney(receiver,money); } private void outMoney (String remitTer, int money){ String outSql = "update user_account set money = money - ? where username = ?"; this.getJdbcTemplate().update(outSql, money ,remitTer); } private void innerMoney (String receiver, int money){ String inSql = "update user_account set money = money + ? where username = ?"; this.getJdbcTemplate().update(inSql, money,receiver); } }
3、测试代码
public class Tx_Test_02 { @Test public void test1 (){ String xmlPath = "spring-jdbc-tx-02.xml"; ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(xmlPath); UserAccountService01 accountService = (UserAccountService01) context.getBean("proxyAccountService"); accountService.remittance("jack","tom",1000); } }
四、XML配置事务
首先配置事务管理器,然后配置事务属性,最后基于AOP编程配置事务切入点。
1、核心配置
<!-- 配置事物管理器 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 配置转账接口 --> <bean id="userAccountService01" class="com.spring.mvc.service.impl.UserAccountServiceImpl01"> <property name="jdbcTemplate" ref="jdbcTemplate" /> </bean> <!-- 配置事物详情 --> <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="remittance" propagation="REQUIRED" isolation="DEFAULT"/> </tx:attributes> </tx:advice> <!-- 事务切入点,基于AOP编程 --> <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.spring.mvc.service.UserAccountService01.*(..))"/> </aop:config>
五、基于事务注解
配置事务管理器,并启动事务注解的支持,在目标类或目标方法添加@Transactional
核心注解即可。
1、核心配置
<!-- 配置事物管理器 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 支持事务注解 --> <tx:annotation-driven transaction-manager="txManager" />
2、注解用法
注解写在接口方法上,或者接口实现的方法上效果一样。
public interface UserAccountService02 { @Transactional(rollbackFor = Exception.class) void remittance(String remitTer, String receiver, int money) ; }
六、源代码地址
GitHub·地址 https://github.com/cicadasmile/spring-mvc-parent GitEE·地址 https://gitee.com/cicadasmile/spring-mvc-parent
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Python 和 JS 有什么相似?
Python 是一门运用很广泛的语言,自动化脚本、爬虫,甚至在深度学习领域也都有 Python 的身影。作为一名前端开发者,也了解 ES6 中的很多特性借鉴自 Python (比如默认参数、解构赋值、Decorator等),同时本文会对 Python 的一些用法与 JS 进行类比。不管是提升自己的知识广度,还是更好地迎接 AI 时代,Python 都是一门值得学习的语言。 数据类型 在 Python 中,最常用的能够直接处理的数据类型有以下几种: 数字[整数(int)、浮点型(float)、长整型(long)、复数(complex)] 字符串(str) 布尔值(bool) 空值(None) 除此之外,Python 还提供了列表[list]、字典[dict] 等多种数据类型,这在下文中会介绍。 类型转换与类型判断 与 JS 十分类似,python 也能实现不同数据类型间的强制与隐式转换,例子如下: 强制类型转换: int('3')# 3 str(3.14)# '3.14' float('3.14')# 3.14 # 区别于 JS 只有 Number 一种类型,Python 中数字中的不同...
- 下一篇
一篇文章让你明白CPU缓存一致性协议MESI
CPU高速缓存(Cache Memory) CPU为何要有高速缓存CPU在摩尔定律的指导下以每18个月翻一番的速度在发展,然而内存和硬盘的发展速度远远不及CPU。这就造成了高性能能的内存和硬盘价格及其昂贵。然而CPU的高度运算需要高速的数据。为了解决这个问题,CPU厂商在CPU中内置了少量的高速缓存以解决IO速度和CPU运算速度之间的不匹配问题。在CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就被称为局部性原理。时间局部性(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。比如循环、递归、方法的反复调用等。空间局部性(Spatial Locality):如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。比如顺序执行的代码、连续创建的两个对象、数组等。 带有高速缓存的CPU执行计算的流程程序以及数据被加载到主内存指令和数据被加载到CPU的高速缓存CPU执行指令,把结果写到高速缓存高速缓存中的数据写回主内存 目前流行的多级缓存结构由于CPU的运算速度超越了1级缓存的数据IO能力,CPU厂商又引入了...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS7,8上快速安装Gitea,搭建Git服务器
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS关闭SELinux安全模块
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- MySQL8.0.19开启GTID主从同步CentOS8
- Hadoop3单机部署,实现最简伪集群
- 设置Eclipse缩进为4个空格,增强代码规范
- CentOS7,CentOS8安装Elasticsearch6.8.6