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";
    }*/

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring事务失效原因有以下几个可能: 1. 配置错误:在中,事务的管理是通过A和代理实现的。如果没有正确AOP或代理,事务将无法被管理和应用。例如,没有在文件中启用事务管理器或没有将@Transactional注解应用到需要事务管理的方法上。 2. 异常处理不当:如果在事务方法中抛出了未被捕获的异常,并且该异常没有被正确处理,事务将会回滚失败,从而导致事务失效。确保在事务方法中正确处理异常,或者使用Spring声明式事务(@Transactional)来自动处理异常。 3. 事务传播性设置错误:Spring中的事务传播性定义了一个方法调用是否应该加入到已存在的事务中。如果事务传播性设置错误,可能会导致事务失效。例如,将一个具有REQUIRED_NEW传播性的方法调用插入到一个具有REQUIRED传播性的方法中,将会导致内部方法的事务失效。 4. 数据库引擎不支持事务:某些数据库引擎可能不支持事务,或者需要进行特殊的配置才能启用事务支持。如果使用的数据库引擎不支持事务Spring事务管理功能将无法生效。 5. 配置多数据源时的错误:如果项目中配置了多数据源,并且事务管理器没有正确指定数据源,事务将无法在正确的数据源上生效。 这些是导致Spring事务失效的常见原因,通过检查和排查这些可能性,通常可以解决事务失效的问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值