赞
踩
引言:
在spring中@Transactional提供一种控制事务管理的快捷手段,但是很多人都只是@Transactional简单使用,并未深入了解,其各个配置项的使用方法,本文将深入讲解各个配置项的使用。
更多日志:
JDBC 事务详解:http://blog.csdn.net/qq_19865749/article/details/75369529
Hibernate 事务管理:http://blog.csdn.net/qq_19865749/article/details/75353874
一、 @Transactional的定义
Spring中的@Transactional基于动态代理的机制,提供了一种透明的事务管理机制,方便快捷解决在开发中碰到的问题。在现实中,实际的问题往往比我们预期的要复杂很多,这就要求对@Transactional有深入的了解,以来应对复杂问题。
首先我们来看看@Transactional的代码定义:
二、 使用@Transactional的Spring配置
为了使用基于@Transactional的事务管理,需要在spring-context.xml 中进行如下配置:
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="emf" />
</bean>
<!-- tx:annotation-driven 启用@Transactional 注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
其中引用的 emf 可以为LocalContainerEntityManagerFactory bean:
<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
</bean>
dataSource 指定了该实体管理器工厂bean 所使用的数据源,当采用c3p0 连接池时,查看另一篇日志:
spring 使用 c3p0 连接池:http://blog.csdn.net/qq_19865749/article/details/75376657
同时该LocalContainerEntityManagerFactoryBean 会自动扫描类路径下的persistence.xml 文件,该文件中定义了持久化单元,即定义了dataSource中所指定的数据库中的表与程序中实体的对应关系(基于JPA 提供者)。使用Hibernate 中的JPA 时定义细节查看另一篇日志:
Hibernate 持久化:
本质上,@Transactional使用了JDBC的事务来进行事务控制的。
三、@Transactional 各值作用
1、 @Transactional之value
value这里主要用来指定不同的事务管理器;主要用来满足在同一个系统中,存在不同的事务管理器。比如在Spring中,声明了两种事务管理器txManager1, txManager2.
然后,用户可以根据这个参数来根据需要指定特定的txManager.
那问题是情况下会存在多个事务管理器的情况呢? 当在一个系统中,需要访问多个数据源或者多个数据库,则必然会配置多个事务管理器的。
2、@Transactional之propagation
Propagation支持7种不同的传播机制:
REQUIRED
业务方法需要在一个事务中运行,如果方法运行时,已处在一个事务中,那么就加入该事务,否则自己创建一个新的事务.这是spring默认的传播行为.。
SUPPORTS
如果业务方法在某个事务范围内被调用,则方法成为该事务的一部分,如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行。 MANDATORY只能在一个已存在事务中执行,业务方法不能发起自己的事务,如果业务方法在没有事务的环境下调用,就抛异常
REQUIRES_NEW
业务方法总是会为自己发起一个新的事务,如果方法已运行在一个事务中,则原有事务被挂起,新的事务被创建,直到方法结束,新事务才结束,原先的事务才会恢复执行.
NOT_SUPPORTED
声明方法需要事务,如果方法没有关联到一个事务,容器不会为它开启事务.如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便会恢复执行.
NEVER
声明方法绝对不能在事务范围内执行,如果方法在某个事务范围内执行,容器就抛异常.只有没关联到事务,才正常执行.
NESTED
如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动的事务,则按REQUIRED属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保证点.内部事务回滚不会对外部事务造成影响, 它只对DataSourceTransactionManager 事务管理器起效.
其实大家最感到困惑的是REQUIRED_NEW和NESTED两种不同的传播机制,功能类似,都涉及到了事务嵌套的问题,那两者有何区别呢?该如何正确使用这两种模式呢?
PROPAGATION_REQUIRES_NEW : uses a completely independent transaction for each affected transaction scope. In that case, the underlying physical transactions are different and hence can commit or roll back independently, with an outer transaction not affected by an inner transaction's rollback status.
内部的事务独立运行,在各自的作用域中,可以独立的回滚或者提交;而外部的事务将不受内部事务的回滚状态影响。
ROPAGATION_NESTED : uses a single physical transaction with multiple savepoints that it can roll back to. Such partial rollbacks allow an inner transaction scope to trigger a rollback for its scope, with the outer transaction being able to continue the physical transaction despite some operations having been rolled back. This setting is typically mapped onto JDBC savepoints, so will only work with JDBC resource transactions.
NESTED的事务,基于单一的事务来管理,提供了多个保存点。这种多个保存点的机制允许内部事务的变更触发外部事务的回滚。而外部事务在混滚之后,仍能继续进行事务处理,即使部分操作已经被混滚。 由于这个设置基于JDBC的保存点,所以只能工作在JDBC的机制智商。
由此可知, 两者都是事务嵌套,不同之处在于,内外事务之间是否存在彼此之间的影响;NESTED之间会受到影响,而产生部分回滚,而REQUIRED_NEW则是独立的。
参考日志:http://blog.csdn.net/blueheart20/article/details/44654007/
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。