Spring事务回滚规则,是否只读,超时时间,事务失效

2023-12-21 15:29:27

一:回滚规则

????默认情况下,事务只有遇到运行期异常(RuntimeExcertion的子类)以及 Error 时才会回滚,在遇到检查型(Checked Exception)异常时不会回滚。像 1/0,空指针这些是RuntimeException,而IOException 则算是 Checked Exception,换言之,默认情况下,如果发生IOException并不会导致事务回滚。如果我们希望发生IOException时也能触发事务回滚,那么可以按照如下方式配置:

java配置:

@Transactional(rollbackFor = I0Exception.class)
    public void handle2() {
      jdbcTemplate.update();
      accountService.handle1();
}

xml配置:

rollback-for="java.io.IOException"
<!--配置事务的通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--配置事务的属性,name 表示哪些方法需要添加事务,可以使用通配符-->
            <tx:method name="transfer*" isolation="SERIALIZABLE" propagation="REQUIRED"
            rollback-for="java.io.IOException"/>
            <tx:method name="add*" isolation="SERIALIZABLE" propagation="REQUIRED"  rollback-for="java.io.IOException"/>
            <tx:method name="delete*" isolation="SERIALIZABLE" propagation="REQUIRED"  rollback-for="java.io.IOException"/>
        </tx:attributes>
    </tx:advice>

还可以发生某些异常不回滚则:

java方式

rollbackFor 换成 noRollbackFor 

xml类似。。。

二:是否只读

????只读事务一般设置在查询方法上,但不是所有的查询方法仍需要只读事务,要看具体情况。
????一般来说,如果这个业务方法只有一个查询SQL,那么就没必要添加事务,强行添加最终效果适得其反。但是如果一个业务方法中有多个查询SQL,情况就不一样了:多个查询SQL,默认情况下,每个查询 SQL 都会开启一个独立的事务,这样,如果有并发操作修改了数据,那么多个查询 SQL 就会查到不一样的数据。此时,如果我们开启事务,并设置为只读事务,那么多个查询SQL将被置于同一个事务中,多条相同的 SQL 在该事务中执行将会获取到相同的查询结果。设置事务只读的方式如下: Java 配置:

Java配置

Transactional(readOnly = true)

xml配置

read-only="true"
<tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--配置事务的属性,name 表示哪些方法需要添加事务,可以使用通配符-->
            <tx:method name="transfer*" isolation="SERIALIZABLE" propagation="REQUIRED"
            rollback-for="java.io.IOException"
            read-only="true"/>
        </tx:attributes>
    </tx:advice>

三:超时时间

????超时时间是说一个事务允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。事务超时时间配置方式如下(单位为秒)

Java 配置:

@Transactional(timeout =10)

xml配置

timeout="10"
<tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--配置事务的属性,name 表示哪些方法需要添加事务,可以使用通配符-->
            <tx:method name="transfer*" isolation="SERIALIZABLE" propagation="REQUIRED"
            rollback-for="java.io.IOException"
            read-only="true"
            timeout="10"/>
        </tx:attributes>
    </tx:advice>

在TransactionDefinition中以int的值来表示超时时间,其单位是秒,默认值为-1。

四:事务失效

主要有这样几种情况

  • 异常被catch捕获了

  • 方法非public

  • 非运行时异常(只有配置了才会事务生效)

  • 数据库不支持事务
    数据库不支持事务,spring咋配置都没有用

  • 不是spring bean
    声明式事务主要是通过动态代理来处理事务的,如果你拿到手的UserService对象就是原原本本的UserService(如果自己new了一个UserService就是这种情况),那么事务代码在哪里?没有事务处理的代码,事务自然不会生效。

声明式事务的核心,就是动态代理生成的那个对象,没有用到那个对象,事务就没戏。

文章来源:https://blog.csdn.net/weixin_41987908/article/details/135129585
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。