技术

spring事务(1)

Spring中的事务,主要有以下几个参数

  • value:事务名称
  • transactionManager:事务管理器
  • propagation:传播行为
  • isolation:隔离级别
  • timeout:超时时间,如果在超时时间内事务没有提交,则事务就会被终止(此处会有坑)
  • readOnly:是否只读事务(需要参考所用的数据源是否支持,如mysql支持只读事务)
  • rollbackFor:何时回滚
  • noRollbackFor:在遇到某些异常时,不回滚

传播行为

/**
	 * 加入当前的事务,如果当前没有事务,则创建一个新的事务
	 * spring里面的默认事务隔离级别
	 */
	REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

	/**
	 * 加入当前存在的事务中,如果没有,就以非事务的形式执行
	 */
	SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),

	/**
	 * 加入当前事务,如果当前事务不存在,则会报错
	 */
	MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),

	/**
	 * 创建一个新的事务,如果当前有事务存在,则把当前事务挂起
	 */
	REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

	/**
	 *以非事务的形式执行,如果当前存在事务,会暂停当前的事务 
	 */
	NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),

	/**
	 * 以非事务的形式执行,如果当前存在事务,则报错
	 * Analogous to EJB transaction attribute of the same name.
	 */
	NEVER(TransactionDefinition.PROPAGATION_NEVER),

	/**
	 * 如果当前事务存在,以嵌套事务的形式执行代码,跟PROPAGATION_REQUIRED有些类型,只是不会加入上一个事务,		
	 * 而是以嵌套的形式存在,在嵌套事务开启的时候,上层事务会存储一个savepoint,如果嵌套事务发生了回滚,上层会	 
	 * 恢复到savepoint,当全部提交的时候,该事务才会被提交
	 */
	NESTED(TransactionDefinition.PROPAGATION_NESTED);

隔离级别

Spring中的隔离级别大致跟mysql的隔离级别一样,为四种,Spring中还多一个缺省值

/**
	 * 默认值,默认使用数据库中定义的事务隔离级别
	 */
	DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),

	/**
	 *读未提交,该隔离级别可能会出现以下问题,脏读,不可重复读以及幻读。该隔离级别在允许别的事务能够立马堵到已经  		
	 *做出修改的数据,而不考虑是否提交,如果被修改的数据最终没有提交,就会导致脏读。
	 */
	READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),

	/**
	 *读已提交,能够避免出现脏读的情况,只会读取已经提交后的数据,但是还是会可能导致不可重复读以及幻读,
	 *不可重复读:当存在并发事务时,如果a已经提交了事务,b读取并进行了修改但是还没有提交,此时a又开始了一个事  		
	 *务,并读取了数据,此时b提交事务,就是导致a在提交事务的时候,值已经被b修改了。
	 */
	READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),

	/**
	 *mysql的默认隔离级别是可重复读
	 *可重复读,能够避免脏读,不可重复读的情况,但是还是会出现幻读的情况。该情况会避免事务读取一个未提交的行数   	 
	 *据变更,并且会阻止当并发事务出现,事务读取一行数据,b事务修改该数据,然后a读取到不同的值的情况
	 */
	REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),

	/**
	 *串行读,会对所有涉及到的行都进行加锁,避免别的事务进行写操作,因此在提交之前,第一个事务每次重新读取数据的		
	 *时候,都不会发生变化,避免了幻读的出现。幻读是指a事务在读取数据的时候,b往其中插入了一条数据并且提交了,	 
	 *在a重新读取的时候,多了一条没有读过的数据出来
	 */
	SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);

超时时间

一般如果不设置的话,默认使用的是数据源的事务超时设置时间。如果数据源也没有设置超时时间的话,就很容易会出现坑。详情参考 事务超时时间导致的坑

最好还是设置一个超时时间,并且把耗时长的行为,移到事务外面

RollBackFor

设置需要回滚的情况,如RuntimeException或者自定义的异常类

NoRollbackFor

设置不需要回滚的情况,例如有些异常是我们已知的,并且不想让事务回滚,就可以使用该参数,指定出现该异常时,不回滚