Spring 事务传播方式
事务传播方式是用于多个事务方法间调用,事务在这些方法中间的传播。Spring 支持7种传播方式。
1.PROPAGATION_REQUIRED(默认)
含义:如果当前存在事务,就加入该事务;若当前没有事务,就创建一个新的事务。
2.PROPAGATION_SUPPORTS
含义:如果当前存在事务,就加入该事务;若当前没有事务,就以非事务方式执行
3.PROPAGATION_MANDATORY
含义:当前方法必须在一个已经存在的事务中执行,如果不存在当前事务,就会抛出异常。
4. PROPAGATION_REQUIRES_NEW
含义:无论当前是否存在事务,都会创建一个新的事务。如果当前存在事务,会将当前事务挂起,直到新事务执行完毕
5.PROPAGATION_NOT_SUPPORTED
含义:以非事务方式执行,如果当前存在事务,会将当前事务挂起
6. PROPAGATION_NEVER
含义:以非事务方式执行,如果当前存在事务,会抛出异常。
7. PROPAGATION_NESTED
含义:如果当前存在事务,会在当前事务的嵌套事务中执行;若当前没有事务,就创建一个新的事务。嵌套事务是当前事务的子事务,它有自己的保存点,若嵌套事务回滚,不会影响外层事务,但外层事务回滚会导致嵌套事务回滚
下面我们用Spring 声明式事务管理来看一下 传播方式:PROPAGATION_MANDATORY
使用,比如说有methodA 和methodB 两种方式,其中 methodA 调用methodB
methodA 如下:
public static void main(String[] args) {
ApplicationContext beanFacotory = new ClassPathXmlApplicationContext("beans.xml");
IAccountService accountService = beanFacotory.getBean("accountService",IAccountService.class);
accountService.addMoney("500","tom");
}
methodB 如下:
@Override
@Transactional(propagation = Propagation.MANDATORY)
public void addMoney(String money, String name) {
try {
String sql = "update t_account set money=money+" + money + " where username=\'" + name + "\'";
jdbcTemplate.execute(sql);
} catch (Exception e) {
e.printStackTrace();
}
}
那么methodB 要求 methodA 存在事务管理,但是现在methodA中并不存在事务管理
所以methodB会抛出异常
Exception in thread "main" org.springframework.transaction.IllegalTransactionStateException: No existing transaction found for transaction marked with propagation 'mandatory'
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:360)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:474)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:289)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at jdk.proxy2/jdk.proxy2.$Proxy9.addMoney(Unknown Source)
at com.inspur.Client.main(Client.java:21)
当然上方异常的出现,就是methodB要求,调用者必须使用事务管理,但是我们main方法没有,如果你没有出现对应的异常,需要排查:
调用方法未开启事务:调用带有 MANDATORY
传播行为方法的上层方法没有开启事务。比如,调用 methodB
(MANDATORY
传播行为)的 methodA
没有开启事务。
事务配置问题:事务管理器配置有误,或者没有启用事务管理功能。
代理调用问题:在 Spring 中,事务是基于 AOP 代理实现的。若方法是通过内部调用,而不是通过代理对象调用,事务可能不会生效。
希望对你有所帮助!