SpringBoot学习(六)——事务的管理

一.引入相关配置

  Spring的事务机制使用统一的机制来处理不同数据访问技术的事务处理。Spring的事务机制提供了一个事务管理器PlatformTransactionManager接口,不同的数据访问技术的事务使用不同的接口实现。

数据访问技术 实现
JDBC DataSourceTransactionManager
JPA JpaTransactionManager
Hibernate HibernateTransactionManager
JDO JdoTransactionManager
分布式事务 JtaTransactionManager

  Spring支持声明式事务,即使用注解来选择需要使用事物的方法,它使用@Transactional注解在类上(对该类的所有public方法开启事务)或方法上(对指定方法开启事务)表明开启事务。这是一个AOP的实现操作。
  开启注解事务管理需要在配置类上添加@EnableTransactionManagement注解。而如果使用的是JDBC,则可以省略,因为在DataSourceTransactionManagerAutoConfiguration中已经添加了该注解。
  关于事务管理器,不管是JPA还是JDBC等都实现自接口 PlatformTransactionManager 如果添加的是 spring-boot-starter-jdbc 依赖,框架会默认注入 DataSourceTransactionManager(查看DataSourceTransactionManagerAutoConfiguration类) 实例。如果添加的是 spring-boot-starter-data-jpa 依赖,框架会默认注入 JpaTransactionManager(查看JpaBaseConfiguration类) 实例。

二.Transactional注解的属性

1.value/transactionManager

  可用于指定使用哪个事务管理器,匹配特定PlatformTransactionManager。如果有项目中只有一个事务管理器,则默认使用该事务管理器。如果项目中有多个事务管理器,则需要设置该值(指定事务管理器)或设置默认的事务管理器,如果不指定则会抛出异常。

①.指定事务管理器

  设置@Transactional注解的value或者transactionManager属性。

@Transactional(transactionManager="txManager2")
public class UserServiceImpl implements IUserService{
    //方法
}
②.指定事务管理器

  设置默认事务管理器是通过在配置类上实现TransactionManagementConfigurer接口并重写annotationDrivenTransactionManager()方法。

package com.xin;

import javax.annotation.Resource;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;

@SpringBootApplication
public class Application implements TransactionManagementConfigurer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

    @Resource(name="txManager2")
    private PlatformTransactionManager txManager2;

    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return txManager2;
    }
}

2.propagation

  指定事务的广播行为,事务的传播行为分7种。

①.Propagation.REQUIRED

  支持当前事务,如果不存在,创建一个新的事务。

②.Propagation.SUPPORTS

  支持当前事务,如果不存在,则执行非事务性操作。

③.Propagation.MANDATORY

  支持当前事务,如果不存在则抛出异常。

④.Propagation.REQUIRES_NEW

  创建一个新的事务,如果已经存在事务则并挂起当前事务。

⑤.Propagation.NOT_SUPPORTED

  不开启事务,如果存在事务则暂停当前事务。

⑥.Propagation.NEVER

  不开启事务,如果存在事务抛出异常。

⑦.Propagation.NESTED

  如果当前事务存在,则在嵌套事务中执行,其行为类似于PROPAGATION.REQUIRED。支持JDBC但是不支持JPA与Hibernate。

  REQUIRES_NEW与NESTED的区别
  PROPAGATION_REQUIRES_NEW 启动一个新的,不依赖于环境的 “内部” 事务。这个事务将被完全 commited 或 rolled back 而不依赖于外部事务,它拥有自己的隔离范围,自己的锁,等等。当内部事务开始执行时,外部事务将被挂起,内务事务结束时,外部事务将继续执行。
  另一方面,PROPAGATION_NESTED 开始一个 “嵌套的” 事务,它是已经存在事务的一个真正的子事务。潜套事务开始执行时,它将取得一个 savepoint。如果这个嵌套事务失败,我们将回滚到此 savepoint。潜套事务是外部事务的一部分,只有外部事务结束后它才会被提交。
  由此可见,PROPAGATION_REQUIRES_NEW 和 PROPAGATION_NESTED 的最大区别在于PROPAGATION_REQUIRES_NEW 完全是一个新的事务, 而 PROPAGATION_NESTED 则是外部事务的子事务, 如果外部事务 commit, 潜套事务也会被 commit, 这个规则同样适用于 roll back。

3.isolation

  指定事务的隔离级别,事务的隔离级别有4种。

①.Isolation.READ_UNCOMMITTED

  读未提交。可能会发生脏读,不可重复读和幻读。

②.Isolation.READ_COMMITTED

  读已提交。可以防止脏读,但可能会发生不可重复的读取和幻像读取。

③.Isolation.REPEATABLE_READ

  可重复读。可以防止脏读与不可重复读,但可能出现幻读。

④.Isolation.SERIALIZABLE

  可串行化。可以防止脏读,不可重复读与幻读。

⑤.Isolation.DEFAULT

  该值不是事务隔离级别的分类,而是使用当前数据库的默认隔离级别,Oracle、SQLService是READ_COMMITTED,而MySql是REPEATABLE_READ。

4.timeout

  此事务的超时。默认为基础事务系统的默认超时。

5.readOnly

  默认为false。如果事务是只读的可以设置为true。

6.rollbackFor/rollbackForClassName

  指定捕获哪个异常类会导致事务回滚。

7.noRollbackFor/noRollbackForClassName

  指定捕获哪个异常类不会导致事务回滚。

你可能感兴趣的:(SpringBoot)