spring事务失效原因

    技术2022-07-12  94

    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"; }*/ }
    Processed: 0.013, SQL: 9