编程式事务和声明式事务浅析
事务管理
在spring中,事物管理一般分为两类,编程式事务管理和声明式事务管理。
编程式事务管理,一般我们使用TransactionTemplate来实现。
声明式事物管理本质上是spring AOP的实现,对目标方法进行拦截,在目标方法之前加入事务,在执行完目标方法之后根据执行情况,进行回滚或者提交两种操作。
下面分别介绍两种方式的实现
编程式事务管理
首先是xml配置
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"><property name="transactionManager" ref="transactionManager"></property></bean><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean>
这里配置事务管理器的时候spring为不同的orm框架实现了不同的platformTransactionManager接口实现
事务 | orm框架 |
---|---|
org.springframework.jdbc.datasource.DataSourceTransaction | spring jdbc和ibatis |
org.springframework.orm.hibernate3.Hibernate.TransactionManager | hibernate3.0 |
org.springframework.orm.jpa.JpaTransactionManager | spring data JPA |
org.springframework.jdo.JdoTransactionManager | 持久化机制Jdo |
org.springframework.transaction.jta.JtaTransactionManager | 使用JTA |
常用的主要是上面两种
使用时
this.getTransactionTemplate().execute(new TransactionCallback()){public Object doInTransaction(TransactionStatus arg0){操作数据库语句a操作数据库语句b
}
}
声明式事务管理
它主要是基于AOP实现,在使用时首先配置xml
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property></bean><tx:annotation-driven transaction-manager="transactionManager">
这要我们就可以直接在代码中使用@Transactional注解来开启事务
@Transactionalpublic void deleteUser(Long userId) throws VaException {//操作数据库语句a//操作数据库语句b}
此时如果中途发生异常,已执行的操作会回滚。
springboot使用事务注解@Transactional
springboot使用事务,只需要在类或者方法上标注@Transactional即可。springboot会根据我们使用的orm框架自动配置合适的事务管理器。
但是需要注意的是springboot中使用@Transactional可能失效的问题:
1.Spring 只会回滚运行时、未检查异常(继承自 RuntimeException 的异常)或者 Error和未被catch的异常 这是由于spring底层实现transactionTemplate决定的看源码
public <T> T execute(TransactionCallback<T> action) throws TransactionException {Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {return ((CallbackPreferringPlatformTransactionManager)this.transactionManager).execute(this, action);} else {TransactionStatus status = this.transactionManager.getTransaction(this);Object result;try {result = action.doInTransaction(status);} catch (Error | RuntimeException var5) { //错误和运行期异常this.rollbackOnException(status, var5);throw var5;} catch (Throwable var6) {this.rollbackOnException(status, var6);throw new UndeclaredThrowableException(var6, "TransactionCallback threw undeclared checked exception");}this.transactionManager.commit(status);return result;}}
2.@Transactional 注解只能应用到 public 方法才有效
所以当你有checked类型的异常时,你可以通过设置属性来是注解生效(可以是一个或者多个)
如@Transactional(rollbackFor=RuntimeException.class)
还有如下一些常用参数:
readOnly: 设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false
noRollbackFor:设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚
propagation:设置事务的传播行为
isolation:设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可。
timeout :事务的超时时间,默认值为-1(表示不限时间)。如果超过该时间限制但事务还没有完成,则自动回滚事务,单位为second
因为spring使用AOP技术动态代理来实现@Transactional,但是动态代理有两种,spring如何选择?如果一个类有顶层接口,则默认使用jdk的动态代理来代理,如果直接是一个类,则使用cglib动态代理。
事务的隔离级别
@Transactional(isolation = Isolation.READ_UNCOMMITTED):读取未提交数据(会出现脏读,
不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED):读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ):可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE):串行化
事务传播行为
TransactionDefinition.PROPAGATION_REQUIRED:
如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。这是默认值。
TransactionDefinition.PROPAGATION_REQUIRES_NEW:
创建一个新的事务,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_SUPPORTS:
如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:
以非事务方式运行,如果当前存在事务,则把当前事务挂起。
TransactionDefinition.PROPAGATION_NEVER:
以非事务方式运行,如果当前存在事务,则抛出异常。
TransactionDefinition.PROPAGATION_MANDATORY:
如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
TransactionDefinition.PROPAGATION_NESTED:
如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;
如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
编程式事务和声明式事务浅析相关推荐
- [事务] 编程式事务和声明式事务的优缺点
事务管理在系统开发中是不可缺少的一部分,Spring提供了很好事务管理机制,主要分为编程式事务和声明式事务两种. 关于事务的基础知识,如什么是事务,数据库事务以及Spring事务的ACID.隔离级别. ...
- Spring笔记(4) - Spring的编程式事务和声明式事务详解
一.背景 事务管理对于企业应用而言至关重要.它保证了用户的每一次操作都是可靠的,即便出现了异常的访问情况,也不至于破坏后台数据的完整性.就像银行的自助取款机,通常都能正常为客户服务,但是也难免遇到操作 ...
- react 编程式导航和声明式导航
react中的两种路由导航方法[声明式导航.编程式导航] 主要使用的方法 [Link , NavLink , props, useHistory() ,Route],推荐使用前四个方法,更简单高效 1 ...
- Spring的编程式事务声明式事务 基于注解的声明式事务控制
文章目录 Spring中编程式事务 基于XML的声明式事务控制 基于注解的声明式事务控制 Spring集成web环境 Spring中编程式事务 Spring的事务控制可以分为编程式事务控制和声明式事务 ...
- spring控制事务:声明式事务(XML)事务的传播行为
声明式事务(XML) 使用spring提供的专用于mybatis的事务管理器在xml中声明式事务 声明式事务需要使用到的标签 tx配置 进行<tx 标签的使用需要在xml头部导入命名空间 xml ...
- Spring编程式和声明式事务实例讲解
历史回顾: 可能是最漂亮的Spring事务管理详解 Spring事务管理 Spring支持两种方式的事务管理: 编程式事务管理: 通过Transaction Template手动管理事务,实际应用中很 ...
- 编程式事务和声明式事物
编程式事务 声明式事物
- java编程式事务_Spring编程式和声明式事务实例讲解
Spring事务管理 Spring支持两种方式的事务管理: 编程式事务管理: 通过Transaction Template手动管理事务,实际应用中很少使用, 使用XML配置声明式事务: 推荐使用(代码 ...
- spring编程式和声明式事务控制
可优先参考:@Transactional Spring 事务的深入学习与使用[两万字] 1. 编程式事务控制 @Autowired private RoleMapper roleMapper;@Aut ...
最新文章
- 如何使用 Python 创建一名可操控的角色玩家
- Socket,SocketImpl与SocketImplFactory的关系
- 深度学习训练的小技巧,调参经验。总结与记录。
- Java中重写equals()方法时注意点
- 利用动态规划(DP)解决 Coin Change 问题
- 集成学习(二)——XGBoost
- 自动化办公-Python处理Excel生成试卷
- java学术论文_java毕业设计论文-学术参考网
- 车站计算机系统的简称,AFC计算机系统.ppt
- 郑州等保测评公司有哪些?在哪里?
- UE4插件研发 So Easy
- android exo解码问题,android – exoplayer-自动更改质量不起作用(hls)
- 普通路由器改4g路由器_工业远程管理神器,4G无线路由器更方便
- Testin融资后首个举措:推出O2O一站式测试服务
- Error: [$injector:unpr] angular.js
- (Python)常用高级函数:print的使用
- “新华三杯”全国大学生数字技术大赛预选赛备考资料
- 248Echarts - 3D 曲面(Parametric Surface Rose)
- Vue - 音频播放器插件(vue-aplayer)
- 技能提升之Latex控制图片位置
热门文章
- 单片机开发:不得不了解的看门狗电路
- 被动信息收集(一)nslookup.dig.DNS字典爆破.whois
- 2-6_Cleaning_Data清洗数据
- ArcGIS 中的标准分类方法
- 程序员在家办公太无聊,推荐你看完这十部电影。收货满满
- Word doc/docx 格式文件转换为 MarkDown
- docx转换为doc格式,公式变成图片问题,word2016
- Vue | 显示切换(v-if与v-show,display,visibility与opacity)
- 阿德莱德大学语言班成绩为C,阿德莱德大学语言课程要读多久?先看看你的雅思成绩……...
- python基础知识点大全