Spring中事务的传播行为

一、说在前面

1、当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。


2、事务的传播行为可以由传播属性指定。Spring 定义了 7  种类传播行为:


(1)REQUIRED:如果有事务在运行,当前的方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务里运行。


(2)REQUIRES_NEW:当前的方法必须启动新事务,并在它自己的事务里运行;如果有事务正在运行,应该将它挂起。


(3)MANDATORY:当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常。


(4)NESTED:如果有事务在运行,当前的方法就应该在这个事务的嵌套事务里运行,否则,就启动一个新的事务,并在它自己的事务里运行。


(5)NEVER:当前的方法不应该运行在事务中,如果有运行的事务,就抛出异常。


(6)NOT_SUPPORTED:当前的方法不应该运行在事务中,如果有运行的事务,就将它挂起。


(7)SUPPORTS:如果有事务在运行,当前的方法就在这个事务内运行,否则,它可以不运行在事务中。



二、实例代码如下:


本实例是在上一篇文章Spring中声明式事务管理的例子的基础上进行的,重复代码不在赘述,请翻阅上一篇文章。


1、Cashier接口


package com.at.spring.tx;

import java.util.List;

public interface Cashier {

	public void checkout(String username,List<String> isbns);
}

2、CashierImpl实现类


package com.at.spring.tx;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("cashier")
public class CashierImpl implements Cashier{
	
	@Autowired
	private BookShopService bookShopService;

	@Transactional
	public void checkout(String username, List<String> isbns) {
		for(String isbn:isbns){
			bookShopService.purchase(username, isbn);
		}
	}
}

3、BookShopService接口


package com.at.spring.tx;

public interface BookShopService {

	public void purchase(String username,String isbn);
}

4、BookShopServiceImpl实现类


package com.at.spring.tx;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Service("bookShopService")
public class BookShopServiceImpl implements BookShopService{

	@Autowired
	private BookShopDao bookShopDao;
	
	//添加事务注解
	/**
	 * 使用propagation指定事务的传播行为,即当前的事务方法被另外一个事务方法调用时如何使用事务,
	 * 默认的取值为REQUIRED,即使用被调用方法的事务
	 * REQUIRES_NEW:使用自己的事务,调用的事务方法的事务被挂起。
	 */
	@Transactional(propagation=Propagation.REQUIRED)
	public void purchase(String username, String isbn) {
		//1、获取书的单价
		int price = bookShopDao.findBookPriceByIsbn(isbn);
		
		//2、更新书的库存
		bookShopDao.updateBookStock(isbn);
		
		//3、更新用户余额
		bookShopDao.updateUserAccount(username, price);
	}

}