# Spring事务传播机制 **Repository Path**: XiaoCui1/spring-transaction ## Basic Information - **Project Name**: Spring事务传播机制 - **Description**: 测试spring的事务传播机制demo - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 3 - **Created**: 2020-07-29 - **Last Updated**: 2023-02-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README 事务传播行为是正对嵌套事务而言。即是(需要事务的业务方法)调用(需要事务的业务方法)而言。 ==⚠️注意事项== 在同一个类下有a,b两个方法,且都有事务。 但是a调用b或者b调用a事务都不会生效。原因是spring事务处理实际是基于动态代理生成类进行事务管理的,而直接调用b方法,调用的实际是当前类的b方法,而并非是代理类的方法,所以b方法并不能加入事务处理。 ### REQUEIRED Spring的默认事务传播机制 概念:支持事务,如果业务方法执行时在事务中则加入当前事务,否则新开启一个事务。 外层事务提交了内层才会提交。 内/外层只有有报错,他们都会回滚 (例子2,3) 只要内层方法抛出异常即使外层方法有try catche该事务也会回滚。 (例子1) 内层不存在事物,外层存在事务。即内层加入外层事务。不管内外层报错都会一起回滚事务。(可以很好的理解REQUEIRED的概念) 例子1: ``` //外层方法 @Service @Transactional(propagation = Propagation.REQUIRED) public class AccountServiceImpl implements AccountService { @Autowired private AccountService1 service1; @Autowired private JdbcTemplate jdbcTemplate; @Override public void save(Account account) { String sql = "insert into account (name,money) values (?,?)"; List list = new ArrayList<>(); list.add(account.getName()); list.add(account.getMoney()); jdbcTemplate.update(sql,list.toArray()); try { service1.update(account); }catch (Exception e){ e.printStackTrace(); } } } ``` ``` //内层方法 @Service @Transactional(propagation = Propagation.REQUIRED) public class AccountServiceImpl1 implements AccountService1 { @Autowired private JdbcTemplate jdbcTemplate; @Override public int update(Account account) { String sql = "update account set money = ? where id = ?"; List list = new ArrayList<>(); list.add(account.getMoney()); return jdbcTemplate.update(sql,list.toArray()); } } ``` ==例1结果:内层报错,回滚,外层也回滚== 例子2: ``` //外层方法 @Service @Transactional(propagation = Propagation.REQUIRED) public class AccountServiceImpl implements AccountService { @Autowired private AccountService1 service1; @Autowired private JdbcTemplate jdbcTemplate; @Override public void save(Account account) { String sql = "insert into account (name,money) values (?,?)"; List list = new ArrayList<>(); list.add(account.getName()); list.add(account.getMoney()); jdbcTemplate.update(sql,list.toArray()); service1.update(account); } } ``` ``` //内层方法 @Service @Transactional(propagation = Propagation.REQUIRED) public class AccountServiceImpl1 implements AccountService1 { @Autowired private JdbcTemplate jdbcTemplate; @Override public int update(Account account) { String sql = "update account set money = ? where id = ?"; List list = new ArrayList<>(); list.add(account.getMoney()); return jdbcTemplate.update(sql,list.toArray()); } } ``` 例子3: ``` //外层方法 @Service @Transactional(propagation = Propagation.REQUIRED) public class AccountServiceImpl implements AccountService { @Autowired private AccountService1 service1; @Autowired private JdbcTemplate jdbcTemplate; @Override public void save(Account account) { String sql = "insert into account (name,money) values (?,?)"; List list = new ArrayList<>(); list.add(account.getMoney()); service1.update(account); jdbcTemplate.update(sql,list.toArray()); } } ``` ``` //内层方法 @Service @Transactional(propagation = Propagation.REQUIRED) public class AccountServiceImpl1 implements AccountService1 { @Autowired private JdbcTemplate jdbcTemplate; @Override public int update(Account account) { String sql = "update account set money = ? where id = ?"; List list = new ArrayList<>(); list.add(account.getMoney()); list.add(account.getId()); return jdbcTemplate.update(sql,list.toArray()); } } ``` ==例2,3不论内/外层只要有报错一起回滚== ### REQUERS_NEW 概念:支持事务,每次都会创建一个新事务,如果当前已经在事务中会挂起当前事务。 内层事务结束内层就提交了。不用等外层一起提交。 外层报错回滚不影响内层(例1) 内层报错回滚,外层try-catche,外层不会滚。(例2) 内层报错回滚,抛出异常,如果外层没有try-catche捕获这个异常 外层也会回滚。(例3) 例1: ``` //外层 @Service @Transactional(propagation = Propagation.REQUIRED) public class AccountServiceImpl implements AccountService { @Autowired private AccountService1 service1; @Autowired private JdbcTemplate jdbcTemplate; @Override public void save(Account account) { String sql = "insert into account (name,money) values (?,?)"; List list = new ArrayList<>(); list.add(account.getName()); service1.delete(12); jdbcTemplate.update(sql,list.toArray()); } } ``` ``` //内层 @Service @Transactional(propagation = Propagation.REQUIRES_NEW) public class AccountServiceImpl1 implements AccountService1 { @Autowired private JdbcTemplate jdbcTemplate; @Override public int delete(int id) { String sql = "delete from account where id = ?"; return jdbcTemplate.update(sql,id); } } ``` ==例1:外层报错回滚,内层删除事务生效== 例2: ``` //外层 @Service @Transactional(propagation = Propagation.REQUIRED) public class AccountServiceImpl implements AccountService { @Autowired private AccountService1 service1; @Autowired private JdbcTemplate jdbcTemplate; @Override public void save(Account account) { String sql = "insert into account (name,money) values (?,?)"; List list = new ArrayList<>(); list.add(account.getName()); list.add(account.getMoney()); jdbcTemplate.update(sql,list.toArray()); try { service1.delete(12); }catch (Exception e){ e.printStackTrace(); } } } ``` ``` //内层 @Service @Transactional(propagation = Propagation.REQUIRES_NEW) public class AccountServiceImpl1 implements AccountService1 { @Autowired private JdbcTemplate jdbcTemplate; @Override public int delete(int id) { String sql = "delete from account where id = ? and name = ?"; return jdbcTemplate.update(sql,id); } } ``` ==例2:内层报错抛出异常,外层捕获异常。内层回滚操作。外层继续事务添加成功== 例3: ``` //外层 @Service @Transactional(propagation = Propagation.REQUIRED) public class AccountServiceImpl implements AccountService { @Autowired private AccountService1 service1; @Autowired private JdbcTemplate jdbcTemplate; @Override public void save(Account account) { String sql = "insert into account (name,money) values (?,?)"; List list = new ArrayList<>(); list.add(account.getName()); list.add(account.getMoney()); jdbcTemplate.update(sql,list.toArray()); service1.delete(12); } } ``` ``` //内层 @Service @Transactional(propagation = Propagation.REQUIRES_NEW) public class AccountServiceImpl1 implements AccountService1 { @Autowired private JdbcTemplate jdbcTemplate; @Override public int delete(int id) { String sql = "delete from account where id = ? and name = ?"; return jdbcTemplate.update(sql,id); } } ``` ==内层报错抛出异常,外层没有捕获。内层回滚操作,外层同样回滚操作== ### NESTED 支持事务,如果当前已经在一个事务中了,则嵌套在事务中做一个子事务。如果当前没有事务则开启一个事务。 内层事务结束要等外层事务一起提交 外层回滚内层也回滚 如果只是内层回滚。影响外层。(因为默认是外层的子事务) 如果内层回滚,外层try-catch内层的异常,不影响外层 ### SUPPORTS 支持事务。当前有事务就加入事务。否则不会开启新事务。 外层正常有事务,内层报错。外层回滚,内层回滚。 外层正常有事务,try-catch内层错误。外层回滚,内层回滚。 外层回滚有事物,内层正常。内层回滚,外层回滚。 外层无事务,内层报错。外层提交,内层提交。 ### MANDATORY 支持事务。如果事务已经在一个事务中则加入事务。否则抛出异常。 外层正常有事务,内层报错。 外层回滚,内层回滚。 外层正常无事务,内层报错 外层提交,内层回滚 切跑出异常。 ``` org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory' ``` ### NOT-SUPPORTED 不支持事务。如果已经在一个事务中则挂起这个事务,等待业务方法执行完成后,事务恢复进行。 外层正常有事务,内层报错。外层回滚,内层提交。 外层正常有事务try-catch内层,内层报错。 外层提交,内层提交。 ### NEVER 不支持事务,如果在一个事务中,抛出异常,数据回滚。 外层正常有事务,内层报错。外层回滚,内层回滚。 报错 ``` org.springframework.transaction.IllegalTransactionStateException: Existing transaction found for transaction marked with propagation 'never' ``` 外层正常无事务,内层报错。外层提交,内层提交。 外层报错有事务,内层正常。外层回滚,内层回滚。 https://blog.csdn.net/qq_35493807/article/details/105756761