@Transactional 注解下,事务失效的多种场景

package com.example.api.demo.boke;

import com.example.api.demo.config.exceptions.MyException;
import org.springframework.transaction.annotation.Transactional;

/**
 *  @Transactional
 *  注解下,事务失效的七种场景
 */
public class Transaction {

    /**
     * 1 异常被捕获后没有抛出
     * 当异常被捕获后,并且没有再抛出,那么updateStudentA是不会回滚的。
     */
    @Transactional
    public void updateStudent() {
        this.updateStudentA();
        try {
            int i = 1 / 0;
            this.updateStudentB();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 2 抛出非运行时异常
     * 异步虽然抛出了,但是抛出的是非RuntimeException类型的异常,依旧不会生效。
     */
    @Transactional
    public void updateStudent2() throws MyException{
        this.updateStudentA();
        try {
            int i = 1 / 0;
            this.updateStudentB();
        } catch (Exception e) {
            throw new MyException();
        }
    }

    /**
     * 3 方法内部直接调用
     * 如果先调用updateStudent3(),那么updateStudent3()是不会回滚的,其原因就是@Transactional根本没生成代理,
     */
    public void updateStudent3() throws MyException{
        updateStudentG();
    }
    @Transactional
    public void updateStudentG() throws MyException{
        this.updateStudentA();
        int i = 1 / 0;
    }

    /**
     * 4 新开启一个线程
     * 如下的方式updateStudentA()也不会回滚,因为spring实现事务的原理是通过ThreadLocal把数据库连接绑定到当前线程中,
     * 新开启一个线程获取到的连接就不是同一个了。
     */
    @Transactional
    public void updateStudent4() throws MyException{
        this.updateStudentA();
        try {
            Thread.sleep(1000); //休眠1秒,保证updateStudentA先执行
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        new Thread(() -> {
            int i = 1/0;
        }).start();
    }

    /**
     * 5 注解到private方法上
     * idea直接会给出提示Methods annotated with ‘@Transactional’ must be overridable ,原理很简单,private修饰的方式,spring无法生成动态代理。
     */
    @Transactional
    private void updateStudent5() throws MyException {
        this.updateStudentA();
        int i = 1/0;
    }

    /**
     * 6、 据库本身不支持: mysql数据库,必须设置数据库引擎为InnoDB。
     * 7、 事务传播属性设置错误, 比如设置了:PROPAGATION_NOT_SUPPORIED(以非事务的方式执行,如果当前有事务则把当前事务挂起)
     * 8、 事务方法被final、static修饰
     * 9、 当前类没有被Spring管理
     */


    private void updateStudentB() {
        System.out.println();
    }

    private void updateStudentA() {
        System.out.println();
    }


}
posted @ 2024-06-07 16:49  威兰达  阅读(25)  评论(0编辑  收藏  举报