spring事务问题一

spring事务问题一

今天组长问了一个spring只读事务问题,大概是这样的


class UserMgr{

   @Transactional(readOnly = true)
    public void method1(){
        //查询操作1
        //查询操作2
        method2();
    }

    @Transactional
    public void method2(){
         //更新操作1
         //更新操作2
        throw new RuntimeException("异常了!");
    }
}

问题是method1事务的情况

情况一 在method2中加默认的事物传播方式 required

结果就是事务不生效,报错的原因是,:

org.springframework.dao.TransientDataAccessResourceException: 
### Error updating database.  
Cause: java.sql.SQLException: 
Connection is read-only. Queries leading to data modification are not allowed

为什么会有这种情况?原因就是 metho2 中的事务没有生效,导致认为是普通的方法块,在 method1 中只读事务中当然不允许修改更新了。但是是什么原因让method2事务没有生效,本质原因是 spring 的事务是基于代理的,method1 和 method2 在同一方法内,所以在调用 method2 的时候,没有生成代理类,所以 method2 方法的事务失效

情况2 在method2,事务加止 required_new传播方式


class UserMgr{

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void method2(){
         //更新操作1
         //更新操作2
        throw new RuntimeException("异常了!");
    }
}

结果和情况一是一样,原因当然也是一样

情况三 将method2方法放到其他类中,默认required 传播方式

知道了前两种事务失效的原因之后,既然知道是没有代理才使其事务失效的,那么这次就将 method2 放到其他类中,在调用的时候走代理


class CserMgr{

    @Transactional
    public void method2(){
         //更新操作1
         //更新操作2
        throw new RuntimeException("异常了!");
    }
}

class UserMgr{

   @Transactional(readOnly = true)
    public void method1(){
        //查询操作1
        //查询操作2
        cuserMgr.method2();
    }
}

看执行结果 :

org.springframework.dao.TransientDataAccessResourceException: 
### Error updating database.  
Cause: java.sql.SQLException: 
Connection is read-only. Queries leading to data modification are not allowed

好吧,,既然 method2 都走代理了,还是这样的错误,那是为什么呢。 原因,虽然method2走了代理 ,的确是开启了事物,但是默认是required, 即如果存在事务,则加入当前事务,那当前是只读事务,method2也只有是只读了,所以也不能进行数据修改和更新了

情况四 在情况三的情况下,将method2的事务传播方式改为 required_new


class CserMgr{

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void method2(){
         //更新操作1
         //更新操作2
        throw new RuntimeException("异常了!");
    }
}

看结果 :


java.lang.RuntimeException: 异常了!

好了,终于看到这个异常了,再看看数据库,数据也没有插入进入,所以在这种情况下method2 的事务才真正有效

结论

在遇到只读事务时,如果要其事务生效,需要指定事务的传播方式为required_new, 且走代理的情况

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页