Spring 传播行为java
Spring 中定义的七种传播行为,由于Spring将事务传播行为是交给事务管理器去实现的,因此使用以前第一步就是查看咱们使用的事务管理器是否支持下面的七中传播行为:spring
PROPAGATION_REQUIRED - -支持当前事务,若是当前没有事务,就新建一个事务。这是最多见的选择。
PROPAGATION_SUPPORTS - -支持当前事务,若是当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY - -支持当前事务,若是当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW - -新建事务,若是当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED - -以非事务方式执行操做,若是当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER - -以非事务方式执行,若是当前存在事务,则抛出异常。 测试
我使用的是:org.springframework.jdbc.datasource.DataSourceTransactionManager 并非彻底是支持这七种传播行为的因此就有不少问题,使用其余的时候必定要关注一下,开始被坑哭了(DataSourceTransactionManager 不支持 PROPAGATION_NOT_SUPPORTED ,PROPAGATION_REQUIRES_NEW )。ui
上面提了一下七种传播行为的含义,可是只看这个彷佛有一点摸不着头脑,我我的认为传播行为的存在是为了解决各个事务方法之间调用可能出现的问题,(这里就涉及理念对实际可能出现的状况作的一种抽象)。 spa
举一两个例子:传播行为“PROPAGATION_MANDATORY ”这个行为的意思就调用该方法的方法必须是一个事务方法(有点绕),不少时候咱们对那些很是重要的数据进行删除,修改,增长的时候咱们确定但愿他们的处于事务中,改到一半失败了,这个是超级可怕的事情。这个传播行为的价值就体现出来了,保证了调用该行为的方法都是事务方法。还有"PROPAGATION_NEVER ",不容许事务方法调用该方法,由于咱们知道事务方法通常是有时间限制的,像一些超级耗时间的方法,咱们给他加上这个传播行为,就能够提醒事务方法不要再使用这个了(不知足特殊状况哈)。code
上面只是提到一些理念对实际的抽象,传播行为之间最奇特的仍是传播行为之间的组合能够解决不少实际上容易面临的问题。
xml
例如:下面举的例子都要关注事务边界哈:事务
PROPAGATION_REQUIRED and PROPAGATION_REQUIRED 传播行为的组合ci
@Transactional(propagation=Propagation.REQUIRED ,rollbackFor=AcceptPendingException.class) public void testRequiredAndRequired(){ //事务开头 insertInfo1();//包含在了testRequiredAndRequired里面 insertInfo2();//包含在了testRequiredAndRequired里面 //事务结束 } @Transactional(propagation=Propagation.REQUIRED) public void insertInfo1(){ ud.insert(10); // throw new AcceptPendingException(); } @Transactional(propagation=Propagation.REQUIRED) public void insertInfo2(){ ud.insert(11); throw new AbstractMethodError(); } public static void main(String args[]) { ApplicationContext ac = new ClassPathXmlApplicationContext( "com/springinaction/springidol/spring-tx.xml"); UserService us = (UserService) ac.getBean("userService"); us.testRequiredAndRequired(); }
发现传播行为:PROPAGATION_REQUIRED 事务边界内只要抛出异常,结果都会回滚。get
通过测试发现:PROPAGATION_REQUIRES_NEW 传播行为是在DataSourceTransactionManager 中不支持的,和PROPAGATION_REQUIRED 行为是相同的。
PROPAGATION_REQUIRED and Propagation.SUPPORTS 传播行为的组合
@Transactional(propagation = Propagation.REQUIRED,readOnly = false, rollbackFor = AcceptPendingException.class) public void testRquiredAndSupported(){ //事务开始 insertInfo1(); insertInfo2(); //事务结束 } @Transactional(propagation = Propagation.SUPPORTS, rollbackFor = AcceptPendingException.class) public void insertInfo1() { ud.insert(10); throw new AcceptPendingException(); } // @Transactional(propagation = Propagation.REQUIRES_NEW) public void insertInfo2() { ud.insertAccount(11); // throw new AbstractMethodError(); } public static void main(String args[]) { ApplicationContext ac = new ClassPathXmlApplicationContext( "com/springinaction/springidol/spring-tx.xml"); UserService us = (UserService) ac.getBean("userService"); us.insertInfo1(); }
当只有Propagation.SUPPORTS 转播行为的时候是没有事务边界的。当PROPAGATION_REQUIRED 下的SUPPORTS 的时候这个时候事务边界就是当前方法的事务边界。
可见咱们使用传播行为的时候主要就是关注事务的边界。就和能够很好的使用传播行为了。