Spring-事务-01 事务的属性和两个重要的传播行为的详解

1.事务就是一系列的动作,它们被当作一个单独的工作单元,这些动作要么全部完成,要么全部不起作用;

2.四个关键属性:

             -原子性:事务是一个原子操作,由一系列动作组成,事物的原子性确保要么全部完成,要么完全不起作用;

             -一致性:一旦所有事物动作完成,事物就会被提交。数据和资源就处于一种满足业务规则的一致性状态中;

             -隔离性:可能有许多事物会同时处理相同的数据,因此每个事务都应该与其他事务隔离开,防止数据损坏;

             -持久性:   一旦事务完成,无论发生什么系统错误,他的结果都不应该受到影响。通常情况下,事物的结果被写入到持                              久化存储器中。

3.spring的声明式事务的使用:

     配置文件的配置:applicationContext.xml

<!-- 配置事务管理器 -->
	<bean id="transactionManager" 
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"></property>
	</bean>
	
	<!-- 启用事务注解 -->
	<tx:annotation-driven transaction-manager="transactionManager"/>

     在Serviceimpl的方法上面加上事务的注解:

        @Transactional
	@Override
	public void purchase(String username, String isbn) {
		
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {}
		
		//1. 获取书的单价
		int price = bookShopDao.findBookPriceByIsbn(isbn);
		
		//2. 更新数的库存
		bookShopDao.updateBookStock(isbn);
		
		//3. 更新用户余额
		bookShopDao.updateUserAccount(username, price);
	}

4.事务的传播属性:

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

         常用的事物传播行为:

                     -REQURED:如果有事务在运行,当前的方法就在这个事务内运行,否则,就启用一个新的事务,并在自己的事务                                        内运行;

                     -REQURES_NEW: 当前方法必须启动新事务,并在它自己的事物内运行,如果有事务正在运行,应该将它挂起。

Demo:描述:书店买书:买一本书是一个事务;同时买多本书也设置成一个事务,那么当剩余的钱只够每一本书的时候这个事                                        务如何设置传播属性?

代码实现:买一本书的事物:

                    

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

                买多本书:

@Service("cashier")
public class CashierImpl implements Cashier {

	@Autowired
	private BookShopService bookShopService;
	//买多本书也使用了事务的注解
	@Transactional
	@Override
	public void checkout(String username, List<String> isbns) {
		for(String isbn: isbns){
			bookShopService.purchase(username, isbn);
		}
	}

}

               调用方法实现:

        @Test
	public void testTransactionlPropagation(){
		cashier.checkout("AA", Arrays.asList("1001", "1002"));
	}

此时银行卡里的余额只够买1002这本书,则事务如何处理?

bookService purchase() 方法被另一个事务方法 checkout() 调用时 , 它默认会在现有的事务内运行 . 这个默认的传播行为就是 REQUIRED. 因此在 checkout() 方法的开始和终止边界内只有一个事务 . 这个事务只在 checkout() 方法结束的时候被提交 , 结果用户一本书都买不了:如图
这种情况是: @Transactional的默认情况,即 @Transactional(propagation=Propagation.REQUIRED)
Tx1是指checkout()。

第二种情况:

@Transactional(propagation=Propagation.REQUIRES_NEW)

此时在当前事务(买多本书)中,每买一本书都是使用自己(即purchase())的事务,所以可以实现买完第一本书的事务,之后在买第二本的时候由于余额不足,导致买不了事务回滚。

Tx1:checkouot();

Tx2:第一个purchase();

Tx3:第二个purchase();





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值