MyBatisspring的@Transactional注解详细用法(转)

概述

事务管理对于企业应用来说是最主要的,即使出现异常情况,它吗得保证数据的一致性。
Spring Framework对事务管理提供了扳平的泛,其性状如下:

  • 啊不同的事务API提供平等的编程模型,比如JTA(Java Transaction API),
    JDBC, Hibernate, JPA(Java Persistence API暨JDO(Java Data Objects)
  • 支持声明式事务管理,特别是依据注解的声明式事务管理,简单容易用
  • 供比较另外事务API如JTA更简便的编程式事务管理API
  • 跟spring数据看抽象的应有尽有集成

事务管理方式

spring支持编程式事务管理和声明式事务管理两种办法。

编程式事务管理使用TransactionTemplate或者直接用底层的PlatformTransactionManager。对于编程式事务管理,spring推荐使用TransactionTemplate。

声明式事务管理建立在AOP之上的。其精神是针对性法前后进行阻挠,然后以靶措施开始前创建或者参加一个工作,在实践了目标措施后因实施情况提交或者回滚事务。声明式事务最酷之独到之处就是是不需要经过编程的方管理作业,这样即便非欲在业务逻辑代码中混事务管理的代码,只待以布置文件被举行相关的事体规则声明(或经根据@Transactional注解的不二法门),便可将事情规则下及工作逻辑中。

引人注目声明式事务管理要优化编程式事务管理,这多亏spring倡导的非侵入式的开发方式。声明式事务管理使业务代码不深受传染,一个家常的POJO对象,只要添加注解就可博得了的事情支持。和编程式事务相比,声明式事务唯一不足地方是,后者的绝缜密粒度只能作用及点子级别,无法成功像编程式事务那样可以作用及代码片级别。但是就有这样的需,也存诸多变之办法,比如,可以用需要进行事务管理的代码块独立为方式等等。

声明式事务管理也发出个别种常用之法,一栽是基于tx和aop名字空间的xml配置文件,另一样种就是根据@Transactional注解。显然基于注解的措施更简短好用,更舒服。

活动提交(AutoCommit)与连接关闭时之是否自动提交

自动提交

默认情况下,数据库处于活动提交模式。每一样长达告词处于一个单身的工作中,在马上漫长告句执行完毕时,如果实行成功则隐式的交给业务,如果
尽破产则隐式的回滚事务。

对正规的事务管理,是平等组有关的操作处于一个作业间,因此须关闭数据库的活动提交模式。不过,这个我们不用担心,spring会将脚连接的全自动提交特性设置为false。
org/springframework/jdbc/datasource/DataSourceTransactionManager.java

MyBatis 1

 1 // switch to manual commit if necessary. this is very expensive in some jdbc drivers,
 2 // so we don't want to do it unnecessarily (for example if we've explicitly
 3 // configured the connection pool to set it already).
 4 if (con.getautocommit()) {
 5     txobject.setmustrestoreautocommit(true);
 6     if (logger.isdebugenabled()) {
 7         logger.debug("switching jdbc connection [" + con + "] to manual commit");
 8     }
 9     con.setautocommit(false);
10 }

MyBatis 2

有点数据连接池提供了关闭工作自动提交的安装,最好以安装连接池时就将该关闭。但C3P0没有提供及时无异风味,只能拄spring来设置。
因JDBC规范规定,当连接对象建立时应处于活动提交模式,这是跨DBMS的紧缺省值,如果急需,必须显式的闭馆自动提交。C3P0遵守就同业内,让客户代码来显式的设置需要的交模式。

老是关闭时之是不是自动提交

当一个连连关闭时,如果起无提交的政工应什么处理?JDBC规范没有提及,C3P0默认的国策是转滚任何不提交的业务。这是一个正确的政策,但JDBC驱动提供商之间对是问题并不曾上一致。
C3P0的autoCommitOnClose属性默认是false,没有十分必要不若动它。或者好显式的设置此属性为false,这样见面更简明。

依据注解的声明式事务管理配置
spring-servlet.xml

MyBatis 3

1 <!-- transaction support-->
2 <!-- PlatformTransactionMnager -->
3 <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
4     <property name="dataSource" ref="dataSource" />
5 </bean>
6 <!-- enable transaction annotation support -->
7 <tx:annotation-driven transaction-manager="txManager" />

MyBatis 4

还要以spring-servlet.xml中补充加tx名字空间

MyBatis 5

 1 ...
 2     xmlns:tx="http://www.springframework.org/schema/tx"
 3     xmlns:aop="http://www.springframework.org/schema/aop"
 4     xsi:schemaLocation="
 5     ...
 6  
 7 http://www.springframework.org/schema/tx
 8  
 9  
10 http://www.springframework.org/schema/tx/spring-tx.xsd
11  
12     ...

MyBatis 6

MyBatis自动参与到spring事务管理中,无需额外部署,只要org.mybatis.spring.SqlSessionFactoryBean引用的数据源与DataSourceTransactionManager引用的数据源一致即可,否则事务管理会不起作用。

另外要下载依赖包aopalliance.jar放置到WEB-INF/lib目录下。否则spring初始化时会见报好
java.lang.NoClassDefFoundError:
org/aopalliance/intercept/MethodInterceptor

spring事务特性

spring所有的事务管理策略类都连续自org.springframework.transaction.PlatformTransactionManager接口

MyBatis 7

1 public interface PlatformTransactionManager {
2  
3   TransactionStatus getTransaction(TransactionDefinition definition)
4     throws TransactionException;
5  
6   void commit(TransactionStatus status) throws TransactionException;
7  
8   void rollback(TransactionStatus status) throws TransactionException;
9 }

MyBatis 8

其中TransactionDefinition接口定义以下特点:

作业隔离级别

断级别是因多少独冒出的事情间的断程度。TransactionDefinition
接口中定义了五单象征隔离级别的常量:

  • TransactionDefinition.ISOLATION_DEFAULT:这是默认值,表示以底层数据库的默认隔离级别。对多数数据库而言,通常就值就是TransactionDefinition.ISOLATION_READ_COMMITTED。
  • TransactionDefinition.ISOLATION_READ_UNCOMMITTED:该隔离级别表示一个业务可以读取另一个事务修改只是尚尚未提交的数目。该级别不可知防范水污染读,不可再读与幻读,因此好少用该隔离级别。比如PostgreSQL实际上并没此级别。
  • TransactionDefinition.ISOLATION_READ_COMMITTED:该隔离级别表示一个政工只能读取另一个政工都交付的数目。该级别可以防水污染读,这为是多数场面下的推荐值。
  • TransactionDefinition.ISOLATION_REPEATABLE_READ:该隔离级别表示一个政工在总体经过遭到可多次重复执行某查询,并且每次回来的笔录都同样。该级别可以预防脏读和不足再读。
  • TransactionDefinition.ISOLATION_SERIALIZABLE:所有的工作逐项逐个执行,这样工作间就全盘无可能产生干扰,也就是说,该级别可以防止污染读、不可再读与幻读。但是及时将严重影响程序的性能。通常状态下吧未会见就此到拖欠级别。

工作传播行为

所谓事务之传遍行为是乘,如果当上马即事情之前,一个政工及下文已经在,此时发若干挑可以指定一个事务性方法的行行为。在TransactionDefinition定义着连了如下几只代表传播行为之常量:

  • 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。

业务超时

所谓事务超时,就是凭借一个事务所允许实施的极其丰富时,如果超过该时空范围只是事情还尚未成功,则自动回滚事务。在
TransactionDefinition 中坐 int 的价来表示过时间,其单位是秒。

默认设置为根工作系统的超时值,如果底层数据库事务系统并未安装超时值,那么就是是none,没有过限制。

事情只读属性

只有读事务用于客户代码只念而未改数据的动静,只念事务用于特定情景下的优化,比如以Hibernate的时节。
默认为念写作业。

spring事务回滚规则

指令spring事务管理器回滚一个事务之推介方式是在时事情的上下文内抛来深。spring事务管理器会捕捉任何不处理的那个,然后根据规则决定是否回滚抛来怪的事体。

默认配置下,spring只有以抛出的很与否运行时unchecked异常时才转滚该业务,也不怕是废弃来底老与否RuntimeException的子类(Errors也会招业务回滚),而丢弃来checked异常则免会见造成事情回滚。
得显著的布置于抛出那些可怜时回滚事务,包括checked异常。也得明确概念那些很抛来时未回滚事务。

还足以编程性的经过setRollbackOnly()方法来指示一个业务必须回滚,在调用完setRollbackOnly()后而所能实施之绝无仅有操作就回滚。

@Transactional注解

@Transactional属性

 
属性 类型 描述
value String 可选的限定描述符,指定使用的事务管理器
propagation enum: Propagation 可选的事务传播行为设置
isolation enum: Isolation 可选的事务隔离级别设置
readOnly boolean 读写或只读事务,默认读写
timeout int (in seconds granularity) 事务超时时间设置
rollbackFor Class对象数组,必须继承自Throwable 导致事务回滚的异常类数组
rollbackForClassName 类名数组,必须继承自Throwable 导致事务回滚的异常类名字数组
noRollbackFor Class对象数组,必须继承自Throwable 不会导致事务回滚的异常类数组
noRollbackForClassName 类名数组,必须继承自Throwable 不会导致事务回滚的异常类名字数组

 

用法

@Transactional
可以作用被接口、接口方法、类以及近似方式齐。当作用被类及时常,该类的持有
public
方法将都有该档的事务属性,同时,我们啊可以方级别下该标注来覆盖类级别的概念。

尽管如此 @Transactional 注解可以作用被接口、接口方法、类以及近似方式齐,但是
Spring
建议不要以接口或者接口方法上使该注解,因为就只有当采取基于接口的代理时它们才会生效。另外,
@Transactional 注解应该只叫应用至 public 方法齐,这是出于 Spring AOP
的本质决定的。如果您以 protected、private 或者默认可见性的主意齐运用
@Transactional 注解,这将让忽略,也非会见丢来其他异常。

默认情况下,只有来自外部的道调用才见面让AOP代理捕获,也就算是,类中方法调用本类内部的其余方法并无见面唤起事务行为,即使给调用方法运用@Transactional注解进行修饰。

MyBatis 9

 1 @Transactional(readOnly = true)
 2 public class DefaultFooService implements FooService {
 3  
 4   public Foo getFoo(String fooName) {
 5     // do something
 6   }
 7  
 8   // these settings have precedence for this method
 9   //方法上注解属性会覆盖类注解上的相同属性
10   @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
11   public void updateFoo(Foo foo) {
12     // do something
13   }
14 }

MyBatis 10

原文链接:https://www.cnblogs.com/yepei/p/4716112.html

网站地图xml地图