您的位置:首页 > 编程语言 > Java开发

Spring 传播行为(PROPAGATION)

2016-04-16 00:00 519 查看
摘要: Spring 传播行为 7种 PROPAGATION

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 )。
上面提了一下七种传播行为的含义,但是只看这个似乎有一点摸不着头脑,我个人认为传播行为的存在是为了解决各个事务方法之间调用可能出现的问题,(这里就涉及理念对实际可能出现的情况做的一种抽象)。
举一两个例子:传播行为“PROPAGATION_MANDATORY ”这个行为的意思就调用该方法的方法必须是一个事务方法(有点绕),很多时候我们对那些非常重要的数据进行删除,修改,增加的时候我们肯定希望他们的处于事务中,改到一半失败了,这个是超级可怕的事情。这个传播行为的价值就体现出来了,保证了调用该行为的方法都是事务方法。还有"PROPAGATION_NEVER ",不允许事务方法调用该方法,因为我们知道事务方法一般是有时间限制的,像一些超级耗时间的方法,我们给他加上这个传播行为,就可以提醒事务方法不要再使用这个了(不满足特殊情况哈)。
上面只是提到一些理念对实际的抽象,传播行为之间最奇特的还是传播行为之间的组合可以解决很多实际上容易面临的问题。

例如:下面举的例子都要关注事务边界哈:
PROPAGATION_REQUIRED and PROPAGATION_REQUIRED 传播行为的组合
@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 事务边界内只要抛出异常,结果都会回滚。
经过测试发现: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 的时候这个时候事务边界就是当前方法的事务边界。
可见我们使用传播行为的时候主要就是关注事务的边界。就和可以很好的使用传播行为了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: