Spring的事物传播行为
事物的传播属性:
当事务方法被另一个事务方法调用时, 必须指定事务应该如何传播. 例如: 方法可能继续在现有事务中运行(REQUIRED), 也可能开启一个新事务, 并在自己的事务中运行(Required_NEW).
事务的传播行为可以由传播属性(propagation)指定. Spring 定义了 7 种类传播行为.
这里主要理解一下REQUIRED和REQUIRED_NEW
用例子来说明:
比如一个客户去买两本书,但是账户的余额只能买一本书,那这时应该怎么处理呢?处理方法就是:1要么买一本书,2要么两本一起不买
代码说明:
客户买多本书的接口:
package com.jeremy.springTransaction; import java.util.List; public interface cashier { void checkOut(String userName,List<String> isbns); }
实现类:
package com.jeremy.springTransaction; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @Service public class cashierImpl implements cashier { @Autowired BookShopServiceImpl bookShopServiceImpl; @Transactional @Override public void checkOut(String userName, List<String> isbns) { // TODO Auto-generated method stub for (String isbn:isbns) { bookShopServiceImpl.purchase(userName, isbn); } } }
purchase()方法代码:
@Autowired private BookShopDao bookShopDao; @Transactional @Override public void purchase(String username, String isbn) { //1. 获取书的单价 int price = bookShopDao.findBookPriceByIsbn(isbn); //2. 更新数的库存 bookShopDao.updateBookStock(isbn); //3. 更新用户余额 bookShopDao.updateUserAccount(username, price); }
完整代码这里下载:
这里只是举例子
当客户需要买两本书时,就需要调用checkout()方法,并启动事务(tx1),但是checkout()方法又需要调用purchase()方法,而这个方法也有事务(tx2),这时tx2是要重新开启一个事务还是放在tx1事务中运行
当放在事务tx1运行时:也就是事务的传播属性(propagation=REQUIRED)时,运行流程如下:
REQUIRED:在现有的事务内运行,一起提交
所以这时客户一本书也买不了,因为事务tx2、tx3都和事务tx1一起提交
当重新开启一个事务时:也就是事务的传播属性(propagation=REQUIRED_NEW)时,运行流程如下:
EQUIRES_NEW. 它表示该方法必须启动一个新事务, 并在自己的事务内运行. 如果有事务在运行, 就应该先挂起它.
所以这时客户能买一本书,因为事务tx2已经提交了,