`
zpball
  • 浏览: 916960 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

spring事务探索

阅读更多
spring自建事务管理模块。而且这个事务管理是一个抽象设计,可以应用到很多场合,包括普通的DataSource,jta,jms和hibernate上。

要正确使用spring的事务,首先需要了解spring在事务设计上的一些概念
统观spring事务,围绕着两个核心PlatformTransactionManager和TransactionStatus

PlatformTransactionManager直译过来就是平台相关事务,这里的平台指的是“事务源”,包括刚才我说的DataSource,jta等等。这些无一不是一个事务源。广义的说,凡是可以完成事务性操作的对象,都可以设计出相对应的PlatformTransactionManager,只要这个事务源支持commit,rollback和getTransaction语意。

查看spring代码,可以发现这些manager实现事务,就是调用事务源的事务操作方法

比如

HibernateTransactionManager

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();;   
        }   
...   
  
    }  

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();;
		}
...

	}



jdbc 的DataSourceTransactionManager

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();;   
        }   
        ...   
    }  

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();;
		}
		...
	}



那么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中的一段代码
 
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);;  

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);;
这是直接使用transactionManager的例子,可以看到真正执行business logic 的地方是在try当中那段,前后的代码都是为了完成事务管理的。如果每个business logic都要写上那么一段,我肯定是疯了。我们翻出TransactionTemplate的代码看看他怎么化简了我们的代码

 
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;   
    }  

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;
	}


同上面的代码如出一辙,前后是事务处理代码,当中那段result = action.doInTransaction(status);是我们的应用代码。至于action是什么,全看各位的需要了。但是有一点要主要,如果利用TransactionTemplate,那么他不管你扔出什么异常都会回滚事务,但是回滚的是哪个事务呢?继续挖代码

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;   
        }   
    }  

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;
		}
	}
真相大白,是对template所持有的某个transactionManager进行回滚。所以如果你的应用代码用的是事务源a的一些资源,比如到服务器a的一个datasource,但是你的transactionManager管理的是另一些资源,比如服务器b的一个datasource,代码铁定不会正常运行

特别是在一些多事务源的程序里,这点千万不能搞错。如果多个事务源之间要完成全局事务,还是老老实实用分布式事务管理服务吧(jta)

那么TransactionInterceptor是干什么的?这个是spring 的声明式事务的支持方式。因为用TransactionTemplate要硬编码,而且调整事务策略很麻烦(不是说不能调。举个例子原来程序抛出异常A需要回滚,现在不需要要,我就可以把a catch吃掉。这时候template就不会回滚了。但是每次调整都要重写编码。)而用TransactionInterceptor就可以将这些调整写在配置中。我们再来挖TransactionInterceptor的代码

 
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;   
    }  

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;
	}
万变不离其宗。

所以使用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可以不考虑事务,否则可能会出现事务嵌套,增加程序复杂度。
分享到:
评论

相关推荐

    spring基于AOP实现事务

    对于Spring事务管理,我们通常有两种方式:编程式和声明式。编程式事务管理需要在代码中显式地调用begin、commit、rollback等事务控制方法,而声明式事务管理则是在配置文件或注解中声明事务规则,更加简洁且易于...

    spring3和mybatis3的初始探索

    标题 "spring3和mybatis3的初始探索" 涉及到的是两个非常重要的Java开发框架——Spring和MyBatis的集成与应用。Spring是一个全面的后端开发框架,提供了依赖注入、AOP(面向切面编程)、MVC(模型-视图-控制器)等...

    Spring事务处理流程和原理详解

    本篇文章将深入探讨Spring事务处理的流程和原理。 一、事务理论学习 事务是数据库操作的基本单位,它封装了一组数据库操作,要么全部执行,要么全部回滚。事务具有四大特性,即ACID(原子性Atomicity、一致性...

    详尽的Spring2.0学习提纲

    2. 高级特性实践:探索Spring Security、Spring WebSocket、Spring Boot等进阶主题,提升项目开发能力。 通过以上学习,你可以全面掌握Spring 2.0的核心技术和应用,为成为熟练的Spring开发者奠定坚实的基础。在...

    ZK+spring+hibernate的整合

    5. **事务管理**:由于Spring对事务管理的强大支持,我们可以方便地在服务层实现事务控制,确保数据的一致性。 6. **测试与优化**:最后,进行单元测试和集成测试,确保所有功能正常运行。在实际应用中,还需要考虑...

    spring源码+spring所需jar包

    Spring的核心组件如BeanFactory、ApplicationContext、AOP代理等都是源码探索的重点。其中: - **BeanFactory**:它是Spring容器的基础,负责管理bean的创建、初始化和依赖注入。 - **ApplicationContext**:它是...

    spring

    ”表明这是一次尝试性的学习或探索Spring框架的过程。 **Spring框架关键知识点解析** Spring是一个开源的轻量级Java应用开发框架,旨在简化企业级应用程序的开发过程,其核心是控制反转(Inversion of Control, ...

    spring3使用示例

    Spring框架是Java开发中不可或缺的一部分,它为应用程序提供了一个全面的基础设施,支持bean管理、依赖注入、面向切面编程(AOP)、数据访问/对象关系映射(DAO)...总之,这些示例是探索和掌握Spring框架的理想起点。

    spring-framework.zip

    4. **事务管理**:Spring的事务管理是其另一大亮点,它支持编程式和声明式事务管理。声明式事务管理通过@Transactional注解实现,极大地减少了事务管理的代码量。源码中,我们可以看到PlatformTransactionManager...

    官方源码 spring-framework-5.3.4.zip

    《Spring Framework 5.3.4 源码解析与深度探索》 Spring Framework作为Java领域最广泛应用的开源框架之一,其稳定性和灵活性备受开发者喜爱。本次我们关注的是它的5.3.4版本,官方源码的发布为开发者提供了一个深入...

    Spring从入门到精通

    本教程通过深入浅出的方式,引领读者逐步探索Spring的各个重要模块。 首先,从入门的角度,我们需要理解Spring的核心理念——依赖注入(Dependency Injection,DI)。依赖注入是Spring的核心特性,它使得组件之间的...

    构建为eclipse项目的spring源码

    Spring框架是Java开发中最常用的轻量级开源框架之一,它为开发者提供了丰富的功能,包括依赖注入、面向切面编程、事务管理、数据访问等。在Eclipse中构建Spring源码项目,可以帮助我们深入理解Spring的工作原理,...

    spring教案

    Spring框架是Java开发中不可或缺的一部分,它...Spring不仅限于这些,还有更多高级特性如Spring Cloud、Spring Data等,等待你去探索。无论你是初学者还是经验丰富的开发者,Spring都能为你的Java项目带来显著的提升。

    spring 1.2源代码

    4. 如何利用Spring进行事务管理,了解Transaction API的工作机制。 5. 学习Spring如何与各种数据访问技术(如JDBC、Hibernate)集成。 6. 探索Spring的事件模型,理解应用程序组件间的通信方式。 对于希望深入理解...

    spring-spring-spring

    通过"spring-sandbox-master"这个压缩包文件名,我们可以猜测可能包含一个Spring的学习沙箱或者示例项目,用于实践和探索Spring框架的各种功能和用法。在这样的项目中,可能会有配置文件、源代码、测试用例等,帮助...

    spring3 源码 项目

    《Spring3 源码深度探索》 Spring框架作为Java领域中最广泛应用的轻量级框架之一,其设计理念和实现机制一直是开发者关注的焦点。本文将深入解析Spring3的源码,帮助读者理解其核心组件的功能与工作原理,提升对...

    一些Spring的入门与进阶教程

    Spring框架是Java开发中不可或缺的一部分,它以其强大的依赖注入(DI)和面向切面编程(AOP)功能,以及对其他...随着对Spring的深入,还可以探索Spring Boot、Spring Cloud等相关技术,进一步提升自己的Java开发技能。

    spring-framework-2.5.6

    《Spring框架2.5.6深度解析》 Spring框架,作为Java开发中的核心组件,以其模块化、松耦合的设计理念,为开发者提供了强大的企业级应用支持。...每日积累,逐步提升,Spring的世界等待着我们的探索。

    spring 源码四

    五、Spring事务管理 Spring提供了声明式事务管理,基于AOP实现,通过@Transactional注解来标记需要事务处理的方法。在源码中,PlatformTransactionManager接口定义了事务管理的基本操作,而...

Global site tag (gtag.js) - Google Analytics