Spring事务的传播行为、隔离级别、回滚、只读和过期

事务的传播性

- 当事务的方法被另一个事务的方法调用时,必须指定事务应该如何传播。如:方法可能继续在现有的事务中运行,也可能开启一个新的事务,并在自己的事务中运行。

- 事务的传播行为可以由传播属性指定。Spring定义了7种传播行为:


required:如果有事务在运行,当前的方法就在这个事务内运行,否则就开启一个新的事务,并在自己的事务内运行(常用)

required_new:当前的方法必须启动新事务,并在它自己的事务内运行。如果有事务在运行,应该将其挂起。(常用)

supports:如果有事务在运行,当前这个方法就在这个事务内运行,否则它可以不运行在事务中

not_supported:当前的方法不应该运行在事务中,如果有运行的事务则将其挂起

mandatory:当前的方法必须运行在事务内,如果没有正在运行的事务,则抛出异常

never:当前方法不应该运行在事务中,如果有运行的事务,则抛出异常

nested:如果有事务在运行,当前方法就应该在这个事务的嵌套是事务内运行,否则就启动一个新的事务,并在自己的事务内运行


required传播行为:使用调用者的事务


requires_new传播行为:表示该方法必须启动一个新事务,并在自己的事务内运行,如果有事务在运行就先挂起它。



隔离级别、回滚、只读和过期

- 当同一个应用程序或不同应用程序中的多个事务在同一个数据集上并发执行的时候,可能会出现意外的问题。

- 并发导致的问题:

1、脏读:对于两个事务t1、t2,t1读取了已经 被t2更新,但还没有被提交的字段,之后若t2回滚,t1读取的内容就是临时且无效的

2、不可重复读:对于两个事务t1、t2,t1读取了一个字段,然后t2更新了该字段,之后t1再读取同一个字段,值就不同了

3、幻读:对于两个事务t1、t2,t1从一个表中读取了一个字段,然后t2在该表中插入了一些新的行,之后,如果t1再次读取到同一个表就会多出几行

package dao_tx;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author chenpeng
 * @date 2018/6/4 15:29
 */
@Service
public class BookShopServiceImpl implements BookShopService {

    @Autowired
    private BookShopDao bookShopDao;

    //

    /**
     * 1、添加事务注解,使用propagation指定事务的传播行为,即当前事务方法被另一个事务方法调用时,如何使用事务?
     * 默认取值REQUIRED,即使用调用方法的事务
     * REQUIRES_NEW:使用自己的事务,调用方法的事务被挂起
     * 2、isolation:指定事务的隔离级别,默认为READ_COMMITTED
     * 3、默认情况下Spring的声明式事务的所有的运行时异常进行回滚,也可以通过对应的属性进行设置,通常取默认值
     * 4、使用readOnly指定事务是否为只读,表示这个事务只读取数据但不更新数据,这样可以帮助数据库引擎优化事务。
     * 如果真的是一个只读取数据库值的方法,应设置readOnly=true
     * 5、使用timeout 指定强制回滚之前事务可以占用的时间
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW,
                    isolation = Isolation.READ_COMMITTED,
                    noRollbackFor = {UserAccountException.class},
                    readOnly = false,timeout = 1)
    @Override
    public void purchase(String username, String isbn) {
        //1、获取书的单价
        int price = bookShopDao.findBookPriceByIsbn(isbn);
        //2、更新库存
        bookShopDao.updateBookStock(isbn);
        //3、更新用户余额
        bookShopDao.updateUserAccount(username,price);
    }
}


原文地址:https://www.cnblogs.com/huangzhe1515023110/p/9276052.html