Spring的事务
Spring的事务分为,声明式事务管理、编程式事务管理两种类型.由三大接口组成:PlatformTransactionManager(事务管理器)、TransactionDefinition(事务定义)、TransactionStatus(事务状态)。不同的事务管理器会对其进行不同的实现。
声明式事务管理
声明式的事务是无侵入式的,基于AOP,本质来说是对于一个方法执行前创建事务,方法执行后提交或者回滚。由于是基于方法级别的,所以声明式事务无法进行更好的细粒度,比如代码块的事务管理,不过我们可以提取代码块为一个方法来进行声明式事务,以做到更小粒度的事务管理。
Spring声明式事务的使用方式
Spring中声明式事务是由@Transactional来标注当前类和方法使用事务的方式,设置注解的不同属性后,Spring在调用这方法前会使用AOP在方法执行前根据声明的事务属性来创建对应的事务。
Transactional的源码
package org.springframework.transaction.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
/**
* 描述单个方法或类上的事务属性。
* 在类级别,此注释默认情况下适用于声明类及其子类的所有方法。
* 注意,它不适用于类层次结构中的祖先类。
* 需要在本地重新声明方法,以参与子类级别的注释
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
/**
* 指定要使用的事务管理器
*/
@AliasFor("transactionManager")
String value() default "";
/**
* 指定要使用的事务管理器
*/
@AliasFor("value")
String transactionManager() default "";
String[] label() default {};
/**
* 事务传播机制,传播范围
*/
Propagation propagation() default Propagation.REQUIRED;
/**
* 事务的隔离级别
*/
Isolation isolation() default Isolation.DEFAULT;
/**
* 此事务的超时时间(以秒为单位)
*/
int timeout() default -1;
/**
* 此事务的超时时间(以秒为单位)
*/
String timeoutString() default "";
/**
* 事务是否是只读的
*/
boolean readOnly() default false;
/**
* 指定异常一个或者多个,必须Throwable的子类,指示哪些异常类型必须引起事务回滚。
*/
Class<? extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};
/**
* 指定异常一个或者多个,必须Throwable的子类,指示哪些异常类型不需要引起事务回滚。
*/
Class<? extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
}
声明式事务的五个特性
1.事务传播机制
- PROPAGATION_REQUIRED: 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
- PROPAGATION_SUPPORTS: 支持当前事务,如果当前没有事务,就以非事务方式执行。
- PROPAGATION_MANDATORY: 使用当前的事务,如果当前没有事务,就抛出异常。
- PROPAGATION_REQUIRES_NEW: 新建事务,如果当前存在事务,把当前事务挂起。
- PROPAGATION_NOT_SUPPORTED: 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
- PROPAGATION_NEVER: 以非事务方式执行,如果当前存在事务,则抛出异常。
- PROPAGATION_NESTED: 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
2.事务隔离机制
1. DEFAULT (默认)
这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外四个与JDBC的隔离级别相对应。
2. READ_UNCOMMITTED (读未提交)
这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
3. READ_COMMITTED (读已提交)
保证一个事务修改的数据提交后才能被另外一个事务读取,另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
4 .REPEATABLE_READ (可重复读)
这种事务隔离级别可以防止脏读、不可重复读,但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了不可重复读。
5. SERIALIZABLE(串行化)
这是花费最高代价但是最可靠的事务隔离级别,事务被处理为顺序执行。除了防止脏读、不可重复读外,还避免了幻像读。
3.只读
只读是当一个方法多次查询数据库,因为其它事务修改了数据导致不可重复读时,需要设置的属性。
只读如果为true,那么方法中不应该出现增删改。
4.事务超时
设置事务的超时时间
5.回滚规则
Spring是根据异常回滚的,可以指定多个异常来拦截回滚,如果生吞了异常就不会发生回滚。