引自:http://www.iteye.com/topic/11190
spring自建事务管理模块。而且这个事务管理是一个抽象设计,可以应用到很多场合,包括普通的DataSource,jta,jms和hibernate上。
要正确使用spring的事务,首先需要了解spring在事务设计上的一些概念
统观spring事务,围绕着两个核心PlatformTransactionManager和TransactionStatus
PlatformTransactionManager直译过来就是平台相关事务,这里的平台指的是“事务源”,包括刚才我说的DataSource,jta等等。这些无一不是一个事务源。广义的说,凡是可以完成事务性操作的对象,都可以设计出相对应的PlatformTransactionManager,只要这个事务源支持commit,rollback和getTransaction语意。
查看spring代码,可以发现这些manager实现事务,就是调用事务源的事务操作方法
比如
HibernateTransactionManager
[code="java"]protected void doCommit(DefaultTransactionStatus status) {
HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction();
if (status.isDebug()) {
logger.debug("Committing Hibernate transaction on session [" +
txObject.getSessionHolder().getSession() + "]");
}
try {
txObject.getSessionHolder().getTransaction().commit();
}
...
}[/code]
jdbc 的DataSourceTransactionManager
[code="java"]protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Committing JDBC transaction on connection [" + con + "]");
}
try {
con.commit();
}
...
}[/code]
那么PlatformTransactionManager以什么依据处理事务呢?
是TransactionStatus
查看api发现这个接口有三个方法
isNewTransaction() ,isRollbackOnly(),setRollbackOnly()
PlatformTransactionManager就是根据前两个方法决定是否要创建一个新事务,是要递交还是回滚。至于第三个方法是改变事务当前状态的,很多地方都要用到,偏偏PlatformTransactionManager自身好像不怎么用,毕竟事务状态的改变是由程序员代码决定的,不需要一个manager多管闲事。
总结上面所说的,spring的事务由PlatformTransactionManager管理,manager最后调用事务源的方法来实现一个事务过程。而manager通过TransactionStatus 来决定如何实现。
接下去说spring事务中的TransactionTemplate和TransactionInterceptor
TransactionTemplate其实和spring中其他的template的作用类似,起到化简代码的作用,不要被它那么长的名字吓倒了,事实上这个template并不是什么非常核心的对象。如果比较学究派的,可以去看看template设计模式,在此就不再对此赘述了。
为什么要有TransactionTemplate?先来看看如果没有TransactionTemplate,我们的代码该怎么写
先来看看spring reference中的一段代码
[code="java"]DefaultTransactionDefinition def = new DefaultTransactionDefinition()
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = transactionManager.getTransaction(def);
try {
// execute your business logic here
} catch (MyException ex) {
transactionManager.rollback(status);
throw ex;
}
transactionManager.commit(status);[/code]
这是直接使用transactionManager的例子,可以看到真正执行business logic 的地方是在try当中那段,前后的代码都是为了完成事务管理的。如果每个business logic都要写上那么一段,我肯定是疯了。我们翻出TransactionTemplate的代码看看他怎么化简了我们的代码
[code="java"]public Object execute(TransactionCallback action) throws TransactionException {
TransactionStatus status = this.transactionManager.getTransaction(this);
Object result = null;
try {
result = action.doInTransaction(status);
}
catch (RuntimeException ex) {
// transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Error err) {
// transactional code threw error -> rollback
rollbackOnException(status, err);
throw err;
}
this.transactionManager.commit(status);
return result;
}[/code]
同上面的代码如出一辙,前后是事务处理代码,当中那段result = action.doInTransaction(status);是我们的应用代码。至于action是什么,全看各位的需要了。但是有一点要主要,如果利用TransactionTemplate,那么他不管你扔出什么异常都会回滚事务,但是回滚的是哪个事务呢?继续挖代码
[code="java"]private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
if (logger.isDebugEnabled()) {
logger.debug("Initiating transaction rollback on application exception", ex);
}
try {
this.transactionManager.rollback(status);
}
catch (RuntimeException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
}
catch (Error err) {
logger.error("Application exception overridden by rollback error", ex);
throw err;
}
}[/code]
真相大白,是对template所持有的某个transactionManager进行回滚。所以如果你的应用代码用的是事务源a的一些资源,比如到服务器a的一个datasource,但是你的transactionManager管理的是另一些资源,比如服务器b的一个datasource,代码铁定不会正常运行
特别是在一些多事务源的程序里,这点千万不能搞错。如果多个事务源之间要完成全局事务,还是老老实实用分布式事务管理服务吧(jta)
那么TransactionInterceptor是干什么的?这个是spring 的声明式事务的支持方式。因为用TransactionTemplate要硬编码,而且调整事务策略很麻烦(不是说不能调。举个例子原来程序抛出异常A需要回滚,现在不需要要,我就可以把a catch吃掉。这时候template就不会回滚了。但是每次调整都要重写编码。)而用TransactionInterceptor就可以将这些调整写在配置中。我们再来挖TransactionInterceptor的代码
[code="java"]public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be null.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface
Class targetClass = (invocation.getThis() != null) ? invocation.getThis().getClass() : null;
// Create transaction if necessary
TransactionInfo txInfo = createTransactionIfNecessary(invocation.getMethod(), targetClass);
Object retVal = null;
try {
// This is an around advice.
// Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceed();
}
catch (Throwable ex) {
// target invocation exception
doCloseTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
doFinally(txInfo);
}
doCommitTransactionAfterReturning(txInfo);
return retVal;
}[/code]
万变不离其宗。
所以使用spring的事务管理需要作这些事
1,设置好事务源,比如DataSource,hibernate的session。如果有多个事务源要考虑他们之间是否有全局事务,如果有,老老实实用jta,否则就需要自己写一个manager了
2,设置manager,根据你的事务源选择对应的PlatformTransactionManager
3,选择实现事物的方式,用template还是interceptor。用template代码直观点,但是template所管辖的manager和你应用代码所用的事务源要一致。如果用interceptor千万注意,一定要调用interceptor那个bean,而不是原始的那个target。在坛子上我已经看到至少有两个朋友说spring事物不起作用,从配置和代码上看都正确,这时要好好查查,调用的bean是哪一个。
4,这个是设计问题了,推荐事务处于一个较高层次,比如service上的某个函数,而底层的dao可以不考虑事务,否则可能会出现事务嵌套,增加程序复杂度。
分享到:
相关推荐
探索使用Spring5和MongoDB4.0,如何开启事务 背景 最近项目中用到了Nosql数据库mongodb和SpringMVC框架。随着项目的深入,遇到了一些困难,于是把这些困难的解决记录下来,希望以后能帮助到其他人。 技术介绍 Spring...
面试必考之HashMap源码分析与实现 探索JVM底层奥秘ClassLoader源码分析与案例讲解 面试必备技能之Dubbo企业实战 ...互联网系统垂直架构之Session解决方案 分库分表之后分布式下如何...无处不在的Spring AOP事务及踩过的坑
以Spring 4.2.9版本为基础,进行以下探索。 1.1 Spring是如何处理事务的 即先@Transactional注解是如何完成的。我们先创建一个类TestService,加上@Service和@Transactional注解,随便写一个保存数据的方法。 1.1.1...
资源介绍 本资源是一份完整的基于Spring Boot开发的MVC高校办公室行政事务管理系统...非诚勿扰,我们期待与您共同探索和学习Spring Boot框架与MVC设计模式的奥秘,为高校办公室行政事务管理系统的建设贡献智慧和力量。
本教程由大牛老师操刀,对老版的五大技术做了升级加强和替换更新,对原有技术进行了更加深入的讲解,此外,引入了后起新秀SpringCloud alibaba,满足你对新技术的探索欲望。教程重点讲解了SpringCloud各种组件停止...
需求来源于对日常生活的思考和探索,结合大学生活的经验和经历,发现目前辅导员与学生之间的事务安排与通知的主要途径为各种通讯软件,虽然通过通讯软件能带来一定的便利性,但在使用上的体验始终存在一些不太便利的...
同时,Spring Boot也提供了强大的安全性、事务管理以及数据库集成等功能,为系统的稳定运行提供了保障。 前端采用Vue.js框架,通过其组件化的开发方式,实现了页面的高效渲染和交互。Vue.js的轻量级和灵活性使得...
在任教,法律分析旨在培养学生有效管理、收集、探索和分析各种形式的法律数据。 其目的是让学生具备以下能力: (1) 理解从数据中提取知识的过程,以及特定应用到法律预测等领域; (2) 在涉及数据或分析的法律诉讼中...
SSM框架则作为后端服务的核心,其中Spring负责依赖注入和事务管理,Spring MVC处理请求分发和响应控制,而MyBatis负责数据持久化操作。这种分层架构确保了系统的高内聚、低耦合特性,提升了代码的可维护性和扩展性。...
但是在实践过程中,发现mycat的框架体系把结构化数据库的事务性完全丢失,还包括MYSQL的存储过程无法有效满足。所以整个应用在Doubbo的传递传递变量存在一些参考价值。也许mycat 2.0或TiDB可以解决这个问题。萨斯...
探索iBatis 阅读并概述 仅限Hibernate文档摘要 #文学 用于合同优先SOAP服务开发的 ------------- JPA ------------------------------- Spring Boot Postgresql错误 ------------------- JTA -------------------...
│ Java面试题54.Spring事务的传播特性和隔离级别.mp4 │ Java面试题55.ORM是什么?ORM框架是什么?.mp4 │ Java面试题56.ibatis和hibernate有什么不同.mp4 │ Java面试题57.hibernate对象状态及其转换.mp4 │ Java...
当前微服务的开发框架也非常多,比较著名的有Dubbo、SpringCloud、thrift、grpc等。虽然微服务现在如火如荼,但对其实践其实仍处于探索阶段。很多中小型互联网公司,鉴于经验、技术实力等问题,微服务落地比较困难。...
1.1.1 探索iBATIS的根源 3 1.1.2 理解iBATIS的优势 7 1.2 iBATIS适合应用在何处 10 1.2.1 业务对象模型 11 1.2.2 表现层 11 1.2.3 业务逻辑层 12 1.2.4 持久层 13 1.2.5 关系数据库 15 1.3 使用不同类型的数据库 17 ...
9. 本项目偏向于个人的未知领域探索实现(绝对不是因为偷懒,笑),比如分布式事务如何保证最终一致性等,所以对个别功能定了计划但并没有实现, 比如:百度地图的区域可视化,收获地址管理等(以前的作品都实现过的...
简介Simple-Framework是基于原生Servlet实现的一种轻量级Java Web框架,它具有目前市面上流行的Java Web框架(如Spring、SpringMVC)所具备的核心功能:Bean容器,依赖注入,请求转发控制器,IOC和AOP功能,事务管理...
3.4 探索竞争消费者模式 3.5 重构的作用 3.6 本章小结 第4章 Java EE测试 4.1 容器内测试与容器外测试的对比 4.2 容器内测试 4.3 Java命名和目录接口(JNDI) 4.4 Java数据库连接(JDBC) 4.5 Java事务API(JTA) ...
3.4 探索竞争消费者模式 3.5 重构的作用 3.6 本章小结 第4章 Java EE测试 4.1 容器内测试与容器外测试的对比 4.2 容器内测试 4.3 Java命名和目录接口(JNDI) 4.4 Java数据库连接(JDBC) 4.5 Java事务API(JTA) ...
6.1.3 探索groovytestcase 6.1.4 测试实践 6.2 使用mocks和stubs 6.2.1 mock实战 6.2.2 使用闭包修整(closureurrying)定义测试数据 6.3 使用webtest进行功能测试 6.3.1 安装web...
CMT DEMO(容器管理事务演示) 事务隔离性的一些基础知识 在组件之间实现事务和异步提交事务(NET2.0) 其它 在.NET访问MySql数据库时的几点经验! 自动代码生成器 关于能自定义格式的、支持多语言的、支持多数据库的...