Spring事务详细使用

Spring中事务的基本组件

PlatformTransactionManager

  • 顶层事务管理器接口,在使用事务时只需要关心该接口,不需要关心其实现类
  • 不同的连接方式会有对应的实现类 例如JDBC方式的实现叫**DataSourceTransactionManager**
//管理器负责管理事务的状态变化 包括开启事务 以及提交和回滚
public interface PlatformTransactionManager extends TransactionManager {
	
	TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
			throws TransactionException;

	void commit(TransactionStatus status) throws TransactionException;

	
	void rollback(TransactionStatus status) throws TransactionException;

}

TransactionDefinition

  • 创建事务的所需的参数接口,**TransactionDefinition**为顶层接口,在该接口中**定义了很多常量**,并且对其中的方法通过**default设置了默认实现**
  • 在使用中通常会使用实现类**DefaultTransactionDefinition** ,来完成参数创建的需求
  • 主要包含五种属性,**隔离性****传播性****回滚规则****超时时间****是否只读**
public interface TransactionDefinition {
	int PROPAGATION_REQUIRED = 0;

	int PROPAGATION_SUPPORTS = 1;

	int PROPAGATION_MANDATORY = 2;

	int PROPAGATION_REQUIRES_NEW = 3;

	int PROPAGATION_NOT_SUPPORTED = 4;

	int PROPAGATION_NEVER = 5;
	int PROPAGATION_NESTED = 6;

	int ISOLATION_DEFAULT = -1;
	int ISOLATION_READ_UNCOMMITTED = 1;  // same as java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;

	int ISOLATION_READ_COMMITTED = 2;  // same as java.sql.Connection.TRANSACTION_READ_COMMITTED;


	int ISOLATION_REPEATABLE_READ = 4;  // same as java.sql.Connection.TRANSACTION_REPEATABLE_READ;

	int ISOLATION_SERIALIZABLE = 8;  // same as java.sql.Connection.TRANSACTION_SERIALIZABLE;


	int TIMEOUT_DEFAULT = -1;


	default int getPropagationBehavior() {
		return PROPAGATION_REQUIRED;
	}


	default int getIsolationLevel() {
		return ISOLATION_DEFAULT;
	}

	default int getTimeout() {
		return TIMEOUT_DEFAULT;
	}
	default boolean isReadOnly() {
		return false;
	}

	@Nullable
	default String getName() {
		return null;
	}

	static TransactionDefinition withDefaults() {
		return StaticTransactionDefinition.INSTANCE;
	}

}

TransactionStatus

  • 可以理解为事务本身,根据这个类可以获取到事务当前的状态
public interface TransactionStatus extends SavepointManager, Flushable {
 boolean isNewTransaction();
 boolean hasSavepoint();
 void setRollbackOnly();
 boolean isRollbackOnly();
 void flush();
 boolean isCompleted();
}

事务类型

编程式事务

基于PlatformTransactionManager
@Service
public class TransferService {
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Autowired
    PlatformTransactionManager txManager;

    public void transfer() {
        DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
        TransactionStatus status = txManager.getTransaction(definition);
        try {
            jdbcTemplate.update("update user set account=account+100 where username='zhangsan'");
            int i = 1 / 0;
            jdbcTemplate.update("update user set account=account-100 where username='lisi'");
            txManager.commit(status);
        } catch (DataAccessException e) {
            e.printStackTrace();
            txManager.rollback(status);
        }
    }
}

基于TransactionTemplate
@Service
public class TransferService {
    @Autowired
    JdbcTemplate jdbcTemplate;
    @Autowired
    TransactionTemplate tranTemplate;
    public void transfer() {
        tranTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    jdbcTemplate.update("update user set account=account+100 where username='zhangsan'");
                    int i = 1 / 0;
                    jdbcTemplate.update("update user set account=account-100 where username='lisi'");
                } catch (DataAccessException e) {
                    status.setRollbackOnly();
                    e.printStackTrace();
                }
            }
        });
    }
}

声明式事务

隔离性

  • 在Spring事务中提供了五种隔离级别,默认为default,Spring推荐使用default级别
  • default 级别即为默认级别,即数据库采用什么隔离级别就使用什么隔离级别
  • ISOLATION_READ_UNCOMMITTED 读未提交
  • ISOLATION_READ_COMMITTED 读已提交
  • ISOLATION_REPEATABLE_READ 可重复读
  • ISOLATION_SERIALIZABLE 串行化
int ISOLATION_DEFAULT = -1;

int ISOLATION_READ_UNCOMMITTED = 1;  // same as java.sql.Connection.TRANSACTION_READ_UNCOMMITTED;

int ISOLATION_READ_COMMITTED = 2;  // same as java.sql.Connection.TRANSACTION_READ_COMMITTED;

int ISOLATION_REPEATABLE_READ = 4;  // same as java.sql.Connection.TRANSACTION_REPEATABLE_READ;

int ISOLATION_SERIALIZABLE = 8;  // same as java.sql.Connection.TRANSACTION_SERIALIZABLE;

传播性

传播性描述
REQUIRED如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务
SUPPORTS如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行
MANDATORY如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常
REQUIRES_NEW创建一个新的事务,如果当前存在事务,则把当前事务挂起
NOT_SUPPORTED以非事务方式运行,如果当前存在事务,则把当前事务挂起
NEVER以非事务方式运行,如果当前存在事务,则抛出异常
NESTED如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于 TransactionDefinition.PROPAGATION_REQUIRED

REQUIRED(默认级别)

  • 如果方法存在事务,则加入该事务,如果当前方法不存在事务,则自己开启一个事务
  • 假设此时带**有事务的**Method1()调用 级别为 **REQUIRED**的Method2()方法,此时Method2()会**加入**到Method1()的事务中
  • 此时如果Method1()或Method2()中发生异常,则整个事务都会回滚

REQUIRED_NEW

  • 如果当前方法存在事务,则将当前事务挂起,自己创建一个新的事务,如果没有则自己创建一个事务
  • 假设此时带**有事务的**Method1()调用 级别为 **REQUIRED_NEW**的Method2()方法,此时Method2()会创建一个自己的事务
  • 此时如果**Method2()**中出现了异常,则此时Method1() 和 Method2()**都会回滚**,如果Method1()中出现了异常,则此时**只有Method1()会回滚**,而Method2()不会回滚

NESTED

  • 如果当前方法存在事务,则创建一个事务作为该事务的子事务,如果没有则自己创建一个事务
  • 假设此时带事务的Method1()调用 级别为NESTED的Method2()方法,此时Method2()会创建一个自己的事务,并且作为Method1的子事务
  • 此时无论在 Method1()中或是Method2中出现异常,两个方法都会进行回滚操作

回滚操作

  • 即设置出现什么样的异常会进行回滚操作,默认为只有接收到**运行时异常****Error**才会回滚,在遇到**检查型异常不会回滚**
  • 常见的运行时异常有(数组越界、空指针等),但是通常也会遇到许多其他的异常,例如(类型转换错误、SQL错误等),因此在使用中需要将事务的**回滚范围设置为Exception**
  • 在@Transaction注解中,可以配置**rollBackFor**属性和 **noRallBackFor**属性,从而决定事务遇到哪些异常会进行回滚操作, rollBackFor的优先级大于noRallBackFor

只读操作

  • 在@Transaction中,可以设置事务是否为只读事务,如果当设定了为只读事务后,则该事务中只能执行SELECT语句
  • 只读操作通常设置在查询方法中,但不是所有的查询方法都需要添加只读操作,如果一个业务操作中,只有一个读操作,则不需要添加事务,因为事务是消耗性能的
  • 如果在**同一个方法内有多次读操作**,则需要通过事务保证数据的一致性

事务开始和结束时刻

  • 通过 **select * from information_schema.innodb_trx** 可以查询数据库中事务的状态
  • 在Spring中开启了方法时,不会马上在数据库中开启事务,只有在第一次执行语句时,才会在数据库中开启事务

失效场景

  • 数据库本身不支持事务,例如数据库的存储引擎是MyISAM
  • 事务所在的方法没有被Spring管理,例如对象只是一个普通类而不是Bean
  • 方法不是public的
  • 该方法不是被bean调用的,是被同类方法中直接通过方法名进行调用,本质上是this.方法进行调用
  • 异常被捕捉,没有正常抛出到Transaction处
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值