Spring框架Day09之事务传播行为(详解)

事务的传播行为

如果有事务在运行,当前方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行
事务方法的嵌套,传播行为可由传播属性决定。

7个传播属性

required和requires_new

required:先坐老王的车,老王翻车就G了。如果老王没车就自己买一辆车。

requires_new:自己买一辆车,只允许存在自己一辆车,如果老王车也在,则暂时挂起老王的车。如果自己的车又出现问题,自己执行失败。
多个方法同时使用requires_new:将老王的车挂起后,执行完自己的方法业务后,开启老王的车继续行驶

@Transactional(propagation= Propagation.REQUIRED)
/@Transactional(propagation= Propagation.REQUIRES_NEW)
    public void checkout(String username,String isdn) throws FileNotFoundException {
        bookDao.updateStock(isdn);// 减库存
        bookDao.updateBalance(username,bookDao.getPrice(isdn));// 减余额
    }

@Transactional(propagation = Propagation.REQUIRED)
/@Transactional(propagation= Propagation.REQUIRES_NEW)
public void updatePrice(String isbn,int price){
    bookDao.updatePrice(isbn, price);
    int i = 10/0;
}
 
 
@Transactional
public int getPrice(String isbn){
    return bookDao.getPrice(isbn);
}
@Service
public class MultService {
    @Autowired
    private TxBookService bookService;

    @Transactional
    public void mulTx() throws FileNotFoundException {
        // 嵌套事务一(required)
        bookService.checkout("Tom","ISBN-001");

        // 嵌套事务二(required),如果发生异常,嵌套事务一是否回滚都需要设置(使用传播行为)设置这个事务方法是不是和之前的大事务共享一个事务(使用同一条连接)
        bookService.updatePrice("ISBN-002",520);

        int i = 10/0;
    }
}
	 **
     * 多事务
     */
    @Test
    public void test2() throws FileNotFoundException {
        MultService multService = ioc.getBean(MultService.class);
        multService.mulTx();
    }

因为更改价格updatePrice()出现异常,事务全部回滚。

而如果只在结账checkout中使用propagation=Propagation.REQUIRES_NEW,则结账不回滚,更改价格回滚

而如果只在更改价格updatePrice()中使用propagation=Propagation.REQUIES_NEW,则结账回滚,更改价格因出现异常更改失败。

而如果同时在checkout()和updatePrice()中都使用propagation=Propagation.REQUIES_NEW,则结账不回滚,更改价格因出现异常更改失败。

而如果同时在checkout()和updatePrice()中都使用propagation=Propagation.REQUIED,且如果在mulTx()中出现了错误,则都回滚(全在一辆车都翻了会滚了)

而如果在结账中使用propagation=Propagation.REQUIRED,在更改价格中使用propagation=Propagation.REQUIES_NEW,且如果在mulTx()中出现了错误,则结账因为被挂起无效无现象(回滚)而更改价格方法中未出现异常但multx()大体事务中出现了错误,导致只有更改价格更改程度不回滚

multx(){
	// required
	A(){
		// requires_new
		B(){}
		// required
		C(){}
	}
	// requires_new
	D(){
		// requires_new 不崩
		// required 崩
		DDDD(){} 
		E(){
			// requires_new
			F(){
				int i = 10/0;(E/G /A/C崩)
			}
		}
		// requires_new
		G(){}
	}
int i=10/0; (B成功,D整个分支全部成功)
}
结论1:任何处崩,已经执行的requires_new都成功不崩。

如果是required,事务的属性继承于最大事务,在传播行为下的timeout必须设置在原始父事务方法中,才会有超时异常。设置在其他地方等于没设。
如果是requires_new,timeout就设置在当前事务方法就可。

底层:

required:将之前事务用的connection传递给当前方法使用
requires_new:这个方法直接使用新的connection

上一篇:jquery插件


下一篇:[BZOJ3864] Hero meet devil