Spring-事务控制二----事务细节

目录

 一、isolation

二、propagation

 三、noRollbackFor 

四、noRollbackForClassName

五、rollbackFor

六、rollbackForClassName

七、readOnly

八、timeout


 

 

 一、isolation

  • 类型:Isolation
  • 事务的隔离级别:读未提交、读已提交、可重复读、串行化。
  • 有事务的业务逻辑,ioc容器中保存的是这个业务逻辑的代理对象。
  • 使用:
@Transactional(isolation = Isolation.READ_UNCOMMITTED)

  • 根据业务的特性,进行调整。

二、propagation

  • 类型:Propagation
  • 事务的传播行为(事务的传播和行为):设置这个事务是不是和之前的大事务共享同一个事务(使用同一个连接);

如果有多个事务进行嵌套运行,那么子事务是否要和大事务共用一个事务。

    AService{
        //A的一些方法
        
        tx_Mul(){
            tx_A(){

            }
            tx_B(){

            }
        }
    }
  • 例:对于REQUIRED

REQUIRED:required 当前事务和之前的大事务共用一个事务。
如果其中任何一个地方挂了,整个车就爆掉了,就都回滚。



REQUIRES_NEW:当前事务总是使用一个新的事务,如果已经有事务,会将之前的事务挂起。
假设事务A,B都是Requires_New
开启大事务 -> 挂起大事务 -> 开启事务A  ->事务A提交  ->开启事务B ->事务B提交 -开启大事务 ->大事务提交

这时小车之间互相不影响,A爆了回滚A, B和大事务照样运行。

总结:

1、任何处崩,已经执行的requires_new都会成功,不会受到影响。

2、对于REQUIRED的事务,其属性来源于大事务。

意思是说,当一个事务的属性设置为required时,其本身的属性就失效了,比如timeout等,这时属性由其共用事务的大事务的属性决定

Tx_A(){

    
    TX_B(propagation=Propagation.REQUIRED,timeout=5){

    
    }


}

这时B共用A的事务,B的timeout并不会生效,因为它用的属性继承自A,A并没有设置timeout属性。

3、本类事务方法之间的调用就只是一个事务。

对于类外调用XX类的事务方法

MulServiceProxy.mulTx(){

    XXXServiceProxy.tx_A();
    XXXServiceProxy.tx_A();

}

同一个类事务方法互相调用

XXXServiceProxy.mulTx(){
    tx_A();
    tx_B();
}

A和B就没有代理的事务控制了,就只剩mulTx一个事务

BookService

    @Transactional(propagation = Propagation.REQUIRED)
    public void checkout(String userName, String ISBN, Integer number){
        //减库存
        bookDao.updateStock(ISBN, number);
        //计算价格
        float price = bookDao.getPrice(ISBN);
        //减余额
        bookDao.updateBalance(userName, price * number);
    }

    //改价格
    @Transactional(propagation = Propagation.REQUIRED)
    public void updatePrice(String isbn,int price){
        bookDao.updatePrice(isbn,price);
        int i = 10/0;
    }

MulService

@Service
public class MulService {

    @Autowired
    private BookService bookService;

    @Transactional()
    public void mulTx(){
        bookService.checkout("Rocke","ISBN-001",1);

        bookService.updatePrice("ISBN-003",998);
    }
}

在MulService的mulTx这个事务中,调用BookService的两个事务方法,并且其中一个事务存在异常。两个子事务设置的required,即,mulTx存在事务,所以两个字事务方法会共用大事务mulTx的事务。

结果运行失败,全体回滚。

如果把第一个小事务check调整为required_new,这个时候,updatePrice和大事务mulTx共用一个事务,check单独使用一个事务。updatePrice挂了,它自己回滚,check不会受到影响(不回滚)。

REQUIRED:是将之前事务的connection传递过来给这个方法使用。

REQIURES_NEW:是这个方法直接使用新的connection。


 三、noRollbackFor 

  • 对于不同的异常,有不同的处理方式:

运行时异常(非检查异常),可以不处理,默认都回滚;

编译时异常(检查异常),要么try/catch,要么throws,默认不回滚。

  • 事务的回滚:默认发生运行时异常都回滚,发生编译时异常不会回滚
  • 类型:Class<? extends Throwable>[]
  • 指定哪些异常事务可以不回滚,可以让原来默认回滚的异常不回滚。
  • 例:对于运行时异常java.lang.ArithmeticException,默认是回滚的,当我们使用noRollbackFor指定不回滚时:

当异常在事务最后时

​
/*结账:*/
 @Transactional(noRollbackFor = {ArithmeticException.class,NullPointerException.class})
    public void checkout(String userName, String ISBN, Integer number) {
        //减库存
        bookDao.updateStock(ISBN, number);
        //计算价格
        float price = bookDao.getPrice(ISBN);
        //减余额
        bookDao.updateBalance(userName, price * number);
        int i = 10/0;
    }

​

当异常在事务中间时: 减库存而不减余额。也就是异常前的操作执行,异常后的操作不执行。

 /*结账:*/
    @Transactional(noRollbackForClassName = {"java.lang.ArithmeticException"})
    public void checkout(String userName, String ISBN, Integer number) {
        //减库存
        bookDao.updateStock(ISBN, number);
        //计算价格
        int i = 10/0;
        float price = bookDao.getPrice(ISBN);
        //减余额
        bookDao.updateBalance(userName, price * number);
    }
  • 结论:异常照样抛,事务不回滚

 



四、noRollbackForClassName

  • 类型:String[],String全类名
  •  同上
  •  例:
     @Transactional(noRollbackForClassName = {"java.lang.ArithmeticException"})

五、rollbackFor

  •  类型:Class<? extends Throwable>[]
  • 指定哪些异常事务需要回滚,
  • 让原本不回滚的异常(编译时异常)事务回滚。
  •  例:对于FileNotFoundException这个编译时异常,我们选择抛出
    @Transactional(rollbackFor = {FileNotFoundException.class})
    public void checkout(String userName, String ISBN, Integer number) throws FileNotFoundException {
        //减库存
        bookDao.updateStock(ISBN, number);
        //计算价格
        float price = bookDao.getPrice(ISBN);
        //减余额
        bookDao.updateBalance(userName, price * number);
        new FileInputStream("E://Editor");
    }

使用throws抛出异常,事务可以使用rollbackFor指定回滚,而使用try/catch,事务无法指定回滚。


六、rollbackForClassName

  •  类型:String[]
  • 同上

七、readOnly

  •  类型:boolean,默认false
  •  修改事务的只读属性,设置事务为只读事务
  •  可以进行事务优化:当事务的所有操作都是**只读**时,设置readOnly = true,可以加快查询速度,不用管事务的操作了(加锁等等)
  •  但事务有增删改操作时,设置readOnly会抛出异常:
    java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed

八、timeout

  • 类型:int
  • 事务超出指定执行时长后自动终止并回滚
  • 以秒为单位
  • 超时抛出异常并回滚:
    TransactionTimedOutException: Transaction timed out


 

猜你喜欢

转载自blog.csdn.net/weixin_44134725/article/details/111188244