Spring中@Transactional用法详细介绍

Spring中@Transactional用法详细介绍

引言: 在spring中@Transactional提供一种控制事务管理的快捷手段,但是很多人都只是@Transactional简单使用,并未深入了解,其各个配置项的使用方法,本文将深入讲解各个配置项的使用。

1.  @Transactional的定义

Spring中的@Transactional基于动态代理的机制,提供了一种透明的事务管理机制,方便快捷解决在开发中碰到的问题。在现实中,实际的问题往往比我们预期的要复杂很多,这就要求对@Transactional有深入的了解,以来应对复杂问题。

首先我们来看看@Transactional的代码定义:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional { 

  /**
   * A qualifier value for the specified transaction.
   * <p>May be used to determine the target transaction manager,
   * matching the qualifier value (or the bean name) of a specific
   * {@link org.springframework.transaction.PlatformTransactionManager}
   * bean definition.
   */
  String value() default ""; 

  /**
   * The transaction propagation type.
   * Defaults to {@link Propagation#REQUIRED}.
   * @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior()
   */
  Propagation propagation() default Propagation.REQUIRED; 

  /**
   * The transaction isolation level.
   * Defaults to {@link Isolation#DEFAULT}.
   * @see org.springframework.transaction.interceptor.TransactionAttribute#getIsolationLevel()
   */
  Isolation isolation() default Isolation.DEFAULT; 

  /**
   * The timeout for this transaction.
   * Defaults to the default timeout of the underlying transaction system.
   * @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout()
   */
  int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; 

  /**
   * {@code true} if the transaction is read-only.
   * Defaults to {@code false}.
   * <p>This just serves as a hint for the actual transaction subsystem;
   * it will <i>not necessarily</i> cause failure of write access attempts.
   * A transaction manager which cannot interpret the read-only hint will
   * <i>not</i> throw an exception when asked for a read-only transaction.
   * @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly()
   */
  boolean readOnly() default false; 

  /**
   * Defines zero (0) or more exception {@link Class classes}, which must be a
   * subclass of {@link Throwable}, indicating which exception types must cause
   * a transaction rollback.
   * <p>This is the preferred way to construct a rollback rule, matching the
   * exception class and subclasses.
   * <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)}
   */
  Class<? extends Throwable>[] rollbackFor() default {}; 

  /**
   * Defines zero (0) or more exception names (for exceptions which must be a
   * subclass of {@link Throwable}), indicating which exception types must cause
   * a transaction rollback.
   * <p>This can be a substring, with no wildcard support at present.
   * A value of "ServletException" would match
   * {@link javax.servlet.ServletException} and subclasses, for example.
   * <p><b>NB: </b>Consider carefully how specific the pattern is, and whether
   * to include package information (which isn't mandatory). For example,
   * "Exception" will match nearly anything, and will probably hide other rules.
   * "java.lang.Exception" would be correct if "Exception" was meant to define
   * a rule for all checked exceptions. With more unusual {@link Exception}
   * names such as "BaseBusinessException" there is no need to use a FQN.
   * <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(String exceptionName)}
   */
  String[] rollbackForClassName() default {}; 

  /**
   * Defines zero (0) or more exception {@link Class Classes}, which must be a
   * subclass of {@link Throwable}, indicating which exception types must <b>not</b>
   * cause a transaction rollback.
   * <p>This is the preferred way to construct a rollback rule, matching the
   * exception class and subclasses.
   * <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(Class clazz)}
   */
  Class<? extends Throwable>[] noRollbackFor() default {}; 

  /**
   * Defines zero (0) or more exception names (for exceptions which must be a
   * subclass of {@link Throwable}) indicating which exception types must <b>not</b>
   * cause a transaction rollback.
   * <p>See the description of {@link #rollbackForClassName()} for more info on how
   * the specified names are treated.
   * <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(String exceptionName)}
   */
  String[] noRollbackForClassName() default {}; 

}

基于源代码,我们可以发现在@Transactional,原来有这么多的属性可以进行配置,从而达到复杂应用控制的目的。具体各个属性的用法和作用,将在本文的后面逐一进行讲解和说明。

2.  使用@Transactional的Spring配置

为了使用基于@Transactional的事务管理,需要在Spring中进行如下的配置:

 <beans:bean id="transactionManager"
  class="org.springframework.orm.jpa.JpaTransactionManager">
  <beans:property name="dataSource" ref="dataSource" />
  <beans:property name="entityManagerFactory" ref="entityManagerFactory" />
</beans:bean> 

<!-- 声明使用注解式事务 -->
<tx:annotation-driven transaction-manager="transactionManager" />

dataSource是在Spring配置文件中定义的数据源的对象实例,EntityManagerFactory是基于JPA使用的实体类管理器:org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean。这些都是用来配置与数据库的连接信息,本质上,@Transactional使用了JDBC的事务来进行事务控制的。

<annotation-driven>标签的声明,则是在Spring内部启用@Transactional来进行事务管理,类似开关之类的声明。

3.  @Transactional之value

value这里主要用来指定不同的事务管理器;主要用来满足在同一个系统中,存在不同的事务管理器。比如在Spring中,声明了两种事务管理器txManager1, txManager2.

然后,用户可以根据这个参数来根据需要指定特定的txManager.

那有同学会问什么情况下会存在多个事务管理器的情况呢? 比如在一个系统中,需要访问多个数据源或者多个数据库,则必然会配置多个事务管理器的。

4.   @Transactional之propagation

Propagation支持7种不同的传播机制:

REQUIRED

业务方法需要在一个事务中运行,如果方法运行时,已处在一个事务中,那么就加入该事务,否则自己创建一个新的事务.这是spring默认的传播行为.。

SUPPORTS:

如果业务方法在某个事务范围内被调用,则方法成为该事务的一部分,如果业务方法在事务范围外被调用,则方法在没有事务的环境下执行。

MANDATORY:

只能在一个已存在事务中执行,业务方法不能发起自己的事务,如果业务方法在没有事务的环境下调用,就抛异常

REQUIRES_NEW

业务方法总是会为自己发起一个新的事务,如果方法已运行在一个事务中,则原有事务被挂起,新的事务被创建,直到方法结束,新事务才结束,原先的事务才会恢复执行.

NOT_SUPPORTED

声明方法需要事务,如果方法没有关联到一个事务,容器不会为它开启事务.如果方法在一个事务中被调用,该事务会被挂起,在方法调用结束后,原先的事务便会恢复执行.

NEVER:

声明方法绝对不能在事务范围内执行,如果方法在某个事务范围内执行,容器就抛异常.只有没关联到事务,才正常执行.

NESTED:

如果一个活动的事务存在,则运行在一个嵌套的事务中.如果没有活动的事务,则按REQUIRED属性执行.它使用了一个单独的事务, 这个事务拥有多个可以回滚的保证点.内部事务回滚不会对外部事务造成影响, 它只对DataSourceTransactionManager 事务管理器起效.

其实大家最感到困惑的是REQUIRED_NEW和NESTED两种不同的传播机制,功能类似,都涉及到了事务嵌套的问题,那两者有何区别呢?该如何正确使用这两种模式呢?

以下是摘自Spring的文档:

  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则是独立的。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

(0)

相关推荐

  • Spring配置中transactionAttributes的使用方法介绍

    最近碰到这个问题,在使用spring提供的JpaTemplate进行查询时,如果数据量超过100 条,查询效率就会明显降低.由于开始时使用JPA内部的双向关联,造成各实体内部关联过多,从而影响所有的操作,因此怀疑是因为JPA的关联关系所致.但是去掉关联关系后的效果不显著. 查找spring的相关配置,发现原来关于"transactionAttributes"有问题.原来的配置如下: <bean id="baseTransactionProxy" class=&

  • Spring事务Transaction配置的五种注入方式详解

    前段时间对spring的事务配置做了比较深入的研究,在此之间对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的事务配置只要把思路理清,还是比较好掌握的. 总结如下: Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSource.TransactionManager这两部分只是会根据数据访问方式有所变化,

  • Spring中@Transactional用法详细介绍

    Spring中@Transactional用法详细介绍 引言: 在spring中@Transactional提供一种控制事务管理的快捷手段,但是很多人都只是@Transactional简单使用,并未深入了解,其各个配置项的使用方法,本文将深入讲解各个配置项的使用. 1.  @Transactional的定义 Spring中的@Transactional基于动态代理的机制,提供了一种透明的事务管理机制,方便快捷解决在开发中碰到的问题.在现实中,实际的问题往往比我们预期的要复杂很多,这就要求对@Tr

  • js中prototype用法详细介绍

    prototype 是在 IE 4 及其以后版本引入的一个针对于某一类的对象的方法,而且特殊的地方便在于:它是一个给类的对象添加方法的方法!这一点可能听起来会有点乱,别急,下面我便通过实例对这一特殊的方法作已下讲解: 首先,我们要先了解一下类的概念,JavaScript 本身是一种面向对象的语言,它所涉及的元素根据其属性的不同都依附于某一个特定的类.我们所常见的类包括:数组变量(Array).逻辑变量(Boolean).日期变量(Date).结构变量(Function).数值变量(Number)

  • Spring中@Transactional(rollbackFor=Exception.class)属性用法介绍

    序言 今天我在写代码的时候,看到了.一个注解@Transactional(rollbackFor = Exception.class),今天就和大家分享一下,这个注解的用法: 异常 如下图所示,我们都知道Exception分为运行时异常RuntimeException和非运行时异常 error是一定会回滚的 如果不对运行时异常进行处理,那么出现运行时异常之后,要么是线程中止,要么是主程序终止. 如果不想终止,则必须捕获所有的运行时异常,决不让这个处理线程退出.队列里面出现异常数据了,正常的处理应

  • PHP中error_reporting函数用法详细介绍

    PHP中error_reporting函数用法详细介绍 PHP中对错误的处理会用到error_reporting函数,看到最多的是error_reporting(E_ALL ^ E_NOTICE),这个是什么意思呢?下面我们具体分析error_reporting函数. 定义用法 error_reporting() 设置 PHP 的报错级别并返回当前级别. 语法 error_reporting(report_level) 如果参数 report_level 未指定,当前报错级别将被返回.下面几项是

  • Spring在web.xml中的配置详细介绍

    Spring在web.xml中的配置详细介绍 前言      在实际项目中spring的配置文件applicationcontext.xml是通过spring提供的加载机制自动加载到容器中.在web项目中,配置文件加载到web容器中进行解析.目前,spring提供了两种加载器,以供web容器的加载:一种是ContextLoaderListener,另一种是ContextLoaderServlet.这两种在功能上完全相同,只是前一种是基于Servlet2.3版本中新引入的Listener接口实现,

  • Spring中@Async用法详解及简单实例

    Spring中@Async用法 引言: 在Java应用中,绝大多数情况下都是通过同步的方式来实现交互处理的:但是在处理与第三方系统交互的时候,容易造成响应迟缓的情况,之前大部分都是使用多线程来完成此类任务,其实,在spring 3.x之后,就已经内置了@Async来完美解决这个问题,本文将完成介绍@Async的用法. 1.  何为异步调用? 在解释异步调用之前,我们先来看同步调用的定义:同步就是整个处理过程顺序执行,当各个过程都执行完毕,并返回结果. 异步调用则是只是发送了调用的指令,调用者无需

  • nginx命令参数用法详细介绍

    nginx命令参数用法详细介绍 nginx命令:启动nginx 在Windows上安装好nginx后,我们需要启动nginx服务,启动nginx服务的命令行操作主要有两种方式,即 C:/nginx-0.8.53>nginx.exe 或者 C:/nginx-0.8.53>start nginx 启动nginx命令说明:需要注意,由于nginx默认端口也是80端口,如果此时你的机器上开启了Apache或者IIS服务,切忌在启动nginx之前务必关闭IIS或Apache服务,否则nginx启动命令不

  • spring @component的作用详细介绍

    spring @component的作用详细介绍 1.@controller 控制器(注入服务) 2.@service 服务(注入dao) 3.@repository dao(实现dao访问) 4.@component (把普通pojo实例化到spring容器中,相当于配置文件中的<bean id="" class=""/>) @Component,@Service,@Controller,@Repository注解的类,并把这些类纳入进spring容器

  • Java多线程的用法详细介绍

    Java多线程的用法详细介绍 最全面的Java多线程用法解析,如果你对Java的多线程机制并没有深入的研究,那么本文可以帮助你更透彻地理解Java多线程的原理以及使用方法. 1.创建线程 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口.在使用Runnable接口时需要建立一个Thread实例.因此,无论是通过Thread类还是Runnable接口建立线程,都必须建立Thread类或它的子类的实例.Thread构造函数: public Thread( ); publi

  • Python中栈的详细介绍

    目录 1.问题描述 2.解决方案 3.结语 本文转自公众号:"算法与编程之美" 1.问题描述 Python中数据类型有列表,元组,字典,队列,栈,树等等.像列表,元组这样的都是python内置数据结构:栈,队列这些都是需要我们自己去定义的. 栈是一种只允许在一端插入和取出的数据结构,这一端通常被叫做栈顶,另一端叫栈底,没有数据的叫空栈.这种数据类型由于是我们自己进行定义,所以有很多功能都需要自己写出相应函数来实现.所以我们看看这里的功能. 2.解决方案 栈的基本操作大概有:生成栈,入栈

随机推荐