0
点赞
收藏
分享

微信扫一扫

(十二)Spring 事务 - 声明式事务

GhostInMatrix 2022-04-21 阅读 59

(十一)Spring 事务 - JdbcTemplate

1. 声明式事务和编程式事务

beginTransaction();
...
commmit();
...
rollback();
...
connection.autoCommit(false);
...
connection.commit();

而Spring的AOP将事务管理作为一个横切点进行模块化,很好的实现了声明式事务

2. @Transaction事务注解

  • 写在方法上,只在当前方法有效
  • 写在类上,当前类所有的方法都会使用事务
  • 如果类和方法同时存在@Transaction,以方法层为准
  • 标记在方法层上,事务管理控制力度更细,建议放在业务逻辑层,因为业务逻辑层存在嵌套调用

3. 事务属性

3.1 isolation - 事务隔离级别

用于处理事务并发所产生的问题

事务隔离级别脏读可重复读幻读
读未提交
读已提交×
可重复读××
串行化×××
  • 读未提交(READ_UNCOMMITTED)

  • 读已提交(READ_COMMITTED)

  • 可重复读(REPEATABLE_READ)

  • 序列化(SERIALIZABLE)

3.2 propagation - 事务传播行为

事务传播类型外部不存在事务外部存在事务
REQUIRED(默认)开启新的事务融合到外部事务适用增删改查
SUPPORTS不开启新的事务融合到外部事务适用查询
REQUIRES_NEW开启新的事务挂起外部事务,开启新事务适用外部事务和内部事务不相关
NOT_SUPPORTED不开启新的事务挂起外部事务不常用
MANDATORY抛出异常融合到外部事务不常用
NEWSTED开启新的事务开启新事务为外部事务的子事务
NEVER不开启新的事务抛出异常不常用
  • REQUIRED

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
    	 methodB();
    	// do something
    }
     
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodB() {
        // do something
    
    }
    
  • SUPPORTS

    
    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
     	methodB();
    	// do something
    }
     
    // 事务属性为SUPPORTS
    @Transactional(propagation = Propagation.SUPPORTS)
    public void methodB() {
        // do something
    
    }
    
  • REQUIRES_NEW

    @Transactional(propagation = Propagation.REQUIRED)
    public void methodA() {
    	doSomeThingA();
    	methodB();
    	doSomeThingB();
    	// do something else
    }
     
     
    // 事务属性为REQUIRES_NEW
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void methodB() {
        // do something
    
    }
    
    {
        TransactionManager tm = null;
        try{
            //获得一个JTA事务管理器
            tm = getTransactionManager();
            tm.begin();//开启一个新的事务
            Transaction ts1 = tm.getTransaction();
            doSomeThing();
            tm.suspend();//挂起当前事务
            try{
                tm.begin();//重新开启第二个事务
                Transaction ts2 = tm.getTransaction();
                methodB();
                ts2.commit();//提交第二个事务
            } Catch(RunTimeException ex) {
                ts2.rollback();//回滚第二个事务
            } finally {
                //释放资源
            }
            //methodB执行完后,恢复第一个事务
            tm.resume(ts1);
            doSomeThingB();
            ts1.commit();//提交第一个事务
        } catch(RunTimeException ex) {
            ts1.rollback();//回滚第一个事务
        } finally {
            //释放资源
        }
    
    }
    
  • NEWSTED

    @Transactional(propagation = Propagation.REQUIRED)
    methodA(){
      doSomeThingA();
      methodB();
      doSomeThingB();
    }
     
    @Transactional(propagation = Propagation.NEWSTED)
    methodB(){
      ……
    
    }
    
    {
        Connection con = null;
        Savepoint savepoint = null;
        try{
            con = getConnection();
            con.setAutoCommit(false);
            doSomeThingA();
            savepoint = con2.setSavepoint();
            try{
                methodB();
            } catch(RuntimeException ex) {
                con.rollback(savepoint);
            } finally {
                //释放资源
            }
            doSomeThingB();
            con.commit();
        } catch(RuntimeException ex) {
            con.rollback();
        } finally {
            //释放资源
        }
    
    }
    
  • REQUIRED,REQUIRES_NEW,NESTED异同

3.3 timeout - 超时属性

3.4 readOnly - 事务只读

3.5 异常属性设置

  • noRollbackFor - 异常不回滚
  • rollbackFor - 异常回滚
  • 默认对于RuntimeException 及其子类 采用的是回滚的策略;默认对于Exception 及其子类 采用的是提交的策略

4. 实战使用

  • 如果当前业务方法是一组 增、改、删 可以这样设置事务 @Transactional
  • 如果当前业务方法是一组 查询 可以这样设置事务 @Transactionl(readOnly=true)
  • 如果当前业务方法是单个 查询 可以这样设置事务 @Transactionl(propagation=propagation.SUPPORTS ,readOnly=true)
举报

相关推荐

0 条评论