事务的传播属性
当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如,方法可以继续在现有事务中运行,也可能开启一个新的事务,并在自己的事务中运行。
事务的传播行为可以由传播属性指定。Spring定义了7种传播行为。
Spring事务传播行为
传播行为 | 详情 |
---|---|
PROPAGATION_REQUIRED | 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 |
PROPAGATION_SUPPORTS | 支持当前事务,如果当前没有事务,就以非事务方式执行。 |
PROPAGATION_MANDATORY | 支持当前事务,如果当前没有事务,就抛出异常。 |
PROPAGATION_REQUIRES_NEW | 新建事务,如果当前存在事务,把当前事务挂起。 |
PROPAGATION_NOT_SUPPORTED | 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。 |
PROPAGATION_NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常。 |
Spring事务传播实例
创建接口
public interface Cashier {
public void checkout(String username, List<Integer>isbns);
}
实现类
@Service("cashier")
public class CashierImpl implements Cashier {
@Autowired
private BookShopService bookShopService;
@Transactional
@Override
public void checkout(String username, List<Integer> isbns) {
for(Integer isbn: isbns){
bookShopService.purchase(username, isbn);
}
}
}
测试类
public class TransactionTest {
private ApplicationContext ctx = null;
private Cashier cashier = null;
{
ctx = new ClassPathXmlApplicationContext("application-context.xml");
cashier = ctx.getBean(Cashier.class);
}
@Test
public void test(){
cashier.checkout("AA", Arrays.asList(1001));
}
}
当bookService的purchase方法被另一个事务的checkout调用时,它默认会在现有的事务内运行。这个默认的传播行为就是REQUIRED。因此checkout方法开始和终止边界内只有一个事务,这个事务只在checkout方法结束时才提交,结果用户一本书都买不了。
事务传播属性可以在@Transactional注解的propagation属性中定义。
@Transactional(propagation = Propagation.REQUIRED)
网友评论