spring事务失效原因

package study.demo.controller;

import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import study.demo.exception.MyException;

import javax.annotation.PostConstruct;

/**
 * @author :xcz 2020/7/1 11:32
 * 天靈靈地靈靈,代碼不要有問題
 *
 * spring 事务失效
 *
 *
 */

@Service
public class TransactionService {


    /**
     * 1.在异常被自己捕获并且没有重新抛出的情况下会造成事务失效
     * 2.如果抛出的是自定义的检查性Exception的话也是会导致事务失效的,spring的事务只会对Error与RuntimeException及其子类这些异常,做出回滚
     * 2.1 rollbackFor属性 指定我们的自定义异常
     * 2.2 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 进行手动回滚
     * 3. 如果是进行自调用,就会导致失效(即一个类中A方法调用B方法,B方法是有事务注解的)
     * 3.1 通过@Autowired 注入自身的aop代理对象,调用代理对象的事务方法,即可开启事务
     * 3.2 将当前类代理对象暴露到当前线程的局部变量中,进而调用代理对象的方法
     * 3.3 在外部开启事务,这样内部的事务就会包含在外部的事务中
     * 4. 如果spring定义的隔离级别和数据库的不一样,则以spring定义的为准。另外,如果spring设置的隔离级别数据库不支持,效果取决于数据库。
     * 5. spring事务控制放在service层,在service方法中一个方法调用service中的另一个方法,默认只开启一个事务,因为spring事务传播机制默认是将当前事务加到上一个事务上
     * 6. 怎么保证spring事务内的连接唯一性?因为那个Connection在事务开始时封装在了ThreadLocal里,后面事务执行过程中,都是从ThreadLocal中取的,肯定能保证唯一,因为都是在一个线程中执行的!
     * 7.自定义事务管理器
     *     @Bean("myManager")
     *     public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource){
     *         return new DataSourceTransactionManager(dataSource);
     *     }
     */

    private JdbcTemplate jdbcTemplate;

    public TransactionService(JdbcTemplate jdbcTemplate){
        this.jdbcTemplate = jdbcTemplate;
    }

    @Transactional(value = "myManager")
    public String transaction(){
        jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(2,'20190090', 2000, '测试')");
        jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(1,'20190090', 2000, '测试')");
        return "true";
    }

    // 1.在异常被自己捕获并且没有重新抛出的情况下会造成事务失效
    /*@Transactional
    public String transaction(){
        try {
            jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(2,'20190090', 2000, '测试')");
            jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(1,'20190090', 2000, '测试')");
        }catch (Exception e){
            e.printStackTrace();
        }
        return "true";
    }*/

    // 2.如果抛出的是自定义的Exception的话也是会导致事务失效的,spring的事务只会对Error与RuntimeException及其子类这些异常,做出回滚
    /*@Transactional
    public String transaction() throws MyException{
        try {
            jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(2,'20190090', 2000, '测试')");
            jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(1,'20190090', 2000, '测试')");
        }catch (Exception e){
            e.printStackTrace();
            throw new MyException();
        }
        return "true";
    }*/

    // 2.1指定我们的自定义异常
    /*@Transactional(rollbackFor = MyException.class)
    public String transaction() throws MyException{
        try {
            jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(2,'20190090', 2000, '测试')");
            jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(1,'20190090', 2000, '测试')");
        }catch (Exception e){
            e.printStackTrace();
            throw new MyException();
        }
        return "true";
    }*/

    // 2.2TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); 进行手动回滚
    /*@Transactional()
    public String transaction(){
        //jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(2,'20190090', 2000, '测试')");
        jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(2,'20190090', 2000, '测试')");
        TransactionAspectSupport.currentTransactionStatus()
                .setRollbackOnly();
        System.out.println("手动回滚!");

        return "true";
    }*/


    // 3. 如果是进行自调用,就会导致失效
    /*public String transaction(){
        return transaction2();
    }
    @Transactional()
    public String transaction2(){
        jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(2,'20190090', 2000, '测试')");
        jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(1,'20190090', 2000, '测试')");
        return "true";
    }*/

    // 3.1 通过@Autowired 注入自身的aop代理对象,调用代理对象的事务方法,即可开启事务
    /*  @Autowired
    private TransactionService transactionService;

    public String transaction(){
        return transactionService.transaction2();
    }

    @Transactional()
    public String transaction2(){
        jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(2,'20190090', 2000, '测试')");
        jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(1,'20190090', 2000, '测试')");
        return "true";
    }*/


    // 3.2 将当前类代理对象暴露到当前线程的局部变量中,进而调用代理对象的方法
    /*public String transaction(){
        TransactionService transactionService = (TransactionService) AopContext.currentProxy();
        return transactionService.transaction2();
    }

    @Transactional
    public String transaction2(){
        jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(2,'20190090', 2000, '测试')");
        jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(1,'20190090', 2000, '测试')");
        return "true";
    }*/

    // 在外部开启事务,这样内部的事务就会包含在外部的事务中

    /*@Transactional()
    public String transaction(){
        return transaction2();
    }

    @Transactional()
    public String transaction2(){
        jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(2,'20190090', 2000, '测试')");
        jdbcTemplate.update("insert into sp_principle(id,sno,department_id,position) values(1,'20190090', 2000, '测试')");
        return "true";
    }*/

}

你可能感兴趣的:(spring事务失效原因)