假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击http://106.12.206.16:8080/qingruihappy/index.html
我们通过一张图引入
这个怎么实现呢?
我们来看这7中传播行为
Propagation(key属性确定代理应该给哪个方法增加事务行为。这样的属性最重要的部份是传播行为。)有以下选项可供使用:
PROPAGATION_REQUIRED--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
至于事务的传播入门请看
spring事物(2)-----手写spring注解事务&&事务传播行为
下面我们来仔细分析上面的7中行为。
假设有类A的方法methodB(),有类B的方法methodB()。A.methodA()调用B的methodB()方法。这里A.methodA()就是 UserService.add() B.methodB()就是logService.addLog();
一,传播机制1-----PROPAGATION_REQUIRED Transactional默认的
A.methodA()调用B的methodB()方法,那么如果A的方法包含事务,则B的方法则不从新开启事务,
1、 如果B的methodB()抛出异常,A的methodB()没有捕获,则A和B的事务都会回滚;
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); } } public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
2、如果B的methodB()运行期间异常会导致B的methodB()的回滚,A如果捕获了异常,并正常提交事务,则会发生Transaction rolled back because it has been marked as rollback-only的异常。
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { try{ userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); }catch{ } } } public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
3、如果A的methodA()运行期间异常,则A和B的Method的事务都会被回滚
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { userDao.add("test001", 20); logService.addLog(); int i = 1 / 0; userDao.add("test002", 21); } } public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); } }
二,传播机制2----- PROPAGATION_SUPPORTS
如果B的方法methodB()的事务传播特性是propagation_supports,
A.methodA()调用B的methodB()方法,那么如果A的方法包含事务,则B运行在此事务环境中,如果A的方法不包含事务,则B运行在非事务环境;
1、如果A没有事务,则A和B的运行出现异常都不会回滚。
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; public void add() { userDao.add("test001", 20); logService.addLog(); int i = 1 / 0; userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_SUPPORTS) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); } }
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; public void add() { userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_SUPPORTS) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
2、如果A有事务,A的method方法执行抛出异常,B.methodB和A.methodA都会回滚。
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { userDao.add("test001", 20); logService.addLog(); int i = 1 / 0; userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_SUPPORTS) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); } }
3、如果A有事务,B.method抛出异常,B.methodB和A.methodA都会回滚,如果A捕获了B.method抛出的异常,则会出现异常Transactionrolled back because it has been marked as rollback-only。
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_SUPPORTS) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { try{ userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); }catch{ } } } @Transactional(propagation = Propagation.PROPAGATION_SUPPORTS) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
三,传播机制3----- PROPAGATION_MANDATORY
表示当前方法必须在一个事务中运行,如果没有事务,将抛出异常,如下图调用关系:
B.methodB()事务传播特性定义为:PROPAGATION_MANDATORY
1、如果A的methoda()方法没有事务运行环境,则B的methodB()执行的时候会报如下异常:No existingtransaction found for transaction marked with propagation 'mandatory'
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; public void add() { userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_MANDATORY) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
2、如果A的Methoda()方法有事务并且执行过程中抛出异常,则A.methoda()和B.methodb()执行的操作被回滚;
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { userDao.add("test001", 20); logService.addLog(); int i = 1 / 0; userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_MANDATORY) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); } }
3、如果A的methoda()方法有事务,则B.methodB()抛出异常时,A的methoda()和B.methodB()都会被回滚;如果A捕获了B.method抛出的异常,则会出现异常Transaction rolled back because ithas been marked as rollback-only
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); } @Transactional(propagation = Propagation.PROPAGATION_MANDATORY) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { try{ userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); }catch{ } } @Transactional(propagation = Propagation.PROPAGATION_MANDATORY) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
四,传播机制4----- PROPAGATION_NESTED
B的methodB()定义的事务为PROPAGATION_NESTED;
1、如果A的MethodA()不存在事务,则B的methodB()运行在一个新的事务中,B.method()抛出的异常,B.methodB()回滚,但A.methodA()不回滚;如果A.methoda()抛出异常,则A.methodA()和B.methodB()操作不回。
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; public void add() { userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_NESTED) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; public void add() { userDao.add("test001", 20); logService.addLog(); int i = 1 / 0; userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_NESTED) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); } }
2、如果A的methodA()存在事务,则A的methoda()抛出异常,则A的methoda()和B的Methodb()都会被回滚;
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { userDao.add("test001", 20); logService.addLog(); int i = 1 / 0; userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_NESTED) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); } }
3、如果A的MethodA()存在事务,则B的methodB()抛出异常,B.methodB()回滚,如果A不捕获异常,则A.methodA()和B.methodB()都会回滚,如果A捕获异常,则B.methodB()回滚,A不回滚;
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_NESTED) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { try{ userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); }catch{ } } } @Transactional(propagation = Propagation.PROPAGATION_NESTED) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
五,传播机制5----- PROPAGATION_NEVER
表示事务传播特性定义为PROPAGATION_NEVER的方法不应该运行在一个事务环境中
如果B.methodB()的事务传播特性被定义为PROPAGATION_NEVER,则如果A.methodA()方法存在事务,则会出现异常Existingtransaction found for transaction marked with propagation 'never'。
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { try{ userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); }catch{ } } } @Transactional(propagation = Propagation.PROPAGATION_NEVER) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i = 1 / 0; } }
六,传播机制6----- PROPAGATION_REQUIRES_NEW
表示事务传播特性定义为PROPAGATION_REQUIRES_NEW的方法需要运行在一个新的事务中。
如有一下调用关系:B.methodB()事务传播特性为PROPAGATION_REQUIRES_NEW.
1、如果A存在事务,A.methodA()抛出异常,A.methodA()的事务被回滚,但B.methodB()事务不受影响;
如果B.methodB()抛出异常,A不捕获的话,A.methodA()和B.methodB()的事务都会被回滚。
如果A捕获的话,A.methodA()的事务不受影响但B.methodB()的事务回滚。
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { userDao.add("test001", 20); logService.addLog(); int i=1/0; userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_REQUIRES_NEW) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); } }
如果B.methodB()抛出异常,A不捕获的话,A.methodA()和B.methodB()的事务都会被回滚。
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_REQUIRES_NEW) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i=1/0; } }
如果A捕获的话,A.methodA()的事务不受影响但B.methodB()的事务回滚。
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { try{ userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); }catch{ } } } @Transactional(propagation = Propagation.PROPAGATION_REQUIRES_NEW) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i=1/0; } }
七,传播机制7----- PROPAGATION_NOT_SUPPORTED
表示该方法不应该在一个事务中运行。如果有一个事务正在运行,他将在运行期被挂起,直到这个事务提交或者回滚才恢复执行。
如有一下调用关系图:
如果B.methodB()方法传播特性被定义为:PROPAGATION_NOT_SUPPORTED。
1、如果A.methodA()存在事务,如果B.methodB()抛出异常,A.methodA()不捕获的话,A.methodA()的事务被回滚,而B.methodB()出现异常前数据库操作不受影响。如果A.methodA()捕获的话,则A.methodA()的事务不受影响,
B.methodB()异常抛出前的数据操作不受影响。
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21); } } @Transactional(propagation = Propagation.PROPAGATION_NOT_SUPPORTED) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i=1/0; } }
@Service public class UserServiceImplc implements UserService { @Autowired private UserDaoc userDao; @Autowired private LogService logService; @Transactional public void add() { try{ userDao.add("test001", 20); logService.addLog(); userDao.add("test002", 21);}catch{ } } } @Transactional(propagation = Propagation.PROPAGATION_NOT_SUPPORTED) public class LogServiceImpl implements LogService { @Autowired private LogDao logDao; public void addLog() { logDao.add("addLog" + System.currentTimeMillis()); int i=1/0; } }
八,事务的使用案例
1、 在一个话费充值业务处理逻辑中,有如下图所示操作:
业务需要扣款操作和创建订单操作同成功或者失败,因此,charger()和order()的事务不能相互独立,需要包含在chargeHandle()的事务中;
通过以上需求,可以给charge()和order()的事务传播行为定义成:PROPAGATION_MANDATORY
只要charge()或者order()抛出异常整个chargeHandle()都一起回滚,即使chargeHandle()捕获异常也没用,不允许提交事务。
2、 如果业务需求没接受到一次请求到要记录日志到数据库,如下图:
因为log()的操作不管扣款和创建订单成功与否都要生成日志,并且日志的操作成功与否不影响充值处理,所以log()方法的事务传播行为可以定义为:PROPAGATION_REQUIRES_NEW.
3、 在订单的售后处理中,更新完订单金额后,需要自动统计销售报表,如下图所示:
根据业务可知,售后是已经处理完订单的充值请求后的功能,是对订单的后续管理,统计报表report()方法耗时较长,因此,我们需要设置report()的事务传播行为为:PROPAGATION_NEVER,表示不适合在有事务的操作中调用,因为report()太耗时。
4、 在银行新增银行卡业务中,需要执行两个操作,一个是保存银行卡信息,一个是登记新创建的银行卡信息,其中登记银行卡信息成功与否不影响银行卡的创建。
由以上需求,我们可知对于regster()方法的事务传播行为,可以设置为PROPAGATION_NESTED,action()事务的回滚,regster()保存的信息就没意义,也就需要跟着回滚,而regster()的回滚不影响action()事务;insert()的事务传播行为可以设置为PROPAGATION_REQUIRED, PROPAGATION_MANDATORY,即insert()回滚事务,action()的事务必须跟着回滚。
假如你现在还在为自己的技术担忧,假如你现在想提升自己的工资,假如你想在职场上获得更多的话语权,假如你想顺利的度过35岁这个魔咒,假如你想体验BAT的工作环境,那么现在请我们一起开启提升技术之旅吧,详情请点击http://106.12.206.16:8080/qingruihappy/index.html