1. 程式人生 > >Spring 申明式事務&事務的傳播行為

Spring 申明式事務&事務的傳播行為

之前的部落格講述了,為什麼要有事務?https://blog.csdn.net/qq_37591637/article/details/85207922

現在呢?就在原有的基礎上怎麼新增事務,使得整個過程只要有一個地方出問題就失敗,整個過程的成功才叫成功!

換句話說,如果書的庫存夠,賬戶餘額不夠的話,這個過程就失敗,資料庫裡面的庫存和餘額都不會減少!


1.在xml檔案中配置

紅筆標註的顏色都是不可以更改的!固定的模板

<!-- 配置事務管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager
">
<property name="dataSource" ref="datasource"></property>
</bean>
<!-- 使得事務註解生效 -->
<tx:annotation-driven transaction-manager="transactionManager" />


在原來的方法上面只要申明    @Transactional就可以了

package cn.com.day04;

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

@Service("bookShopService")
public class BookShopServiceImpl implements BookShopService{
	@Autowired
	private BookShopDaoImpl bookShopDaoImpl;
	@Transactional
	public void purchase(String username, String isbn) {
		//1.根據書的編號來查詢價格
		int price=bookShopDaoImpl.findBookPriceByIsbn(isbn);
		//2.更新書的庫存
		bookShopDaoImpl.updateBookStock(isbn);
		//2.根據使用者名稱查詢餘額,扣除書的價格
		bookShopDaoImpl.updateUserAccount(username, price);
	}

}

 


 可是新的問題又來了,如果一個客戶去買兩本書,或者是更多的書籍呢?

如果一本是是80元,一本書是30元,可是賬戶餘額裡面只有100元的話,還能買成麼》

這個就涉及到了事務的傳播行為......


程式碼如下

一個介面類(根據使用者名稱,書的編號的集合來模擬實現買書的時候庫存和賬戶餘額的變化)

package cn.com.day04;
import java.util.List;
public interface BookShopList {
public void purchare(String name,List<String> isbns);
}

實現類

package cn.com.day04;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service("bookShopList")
public class BookShopListImpl implements BookShopList {
	@Autowired
	private BookShopService BookShopServiceImpl;
	@Transactional
	public void purchare(String name, List<String> isbns) {
		//一個事務裡面包含多個同樣執行流程的事務,是繼續使用之前的事務還是建立一個新的事務
		for (String isbn : isbns) {
			BookShopServiceImpl.purchase(name, isbn);
		}

	}

}

測試類

package cn.com.day04;

import java.util.Arrays;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestFact {
	private static ApplicationContext ioc = null;
	private static BookShopDaoImpl bookShopDaoImpl = null;
	private static BookShopService bookShopServiceImpl=null;
	private static BookShopList bookShop=null;
	static {
		ioc = new ClassPathXmlApplicationContext("bean-jdbc.xml");
	/*	bookShopDaoImpl = ioc.getBean(BookShopDaoImpl.class);
		bookShopServiceImpl=ioc.getBean(BookShopService.class);*/
		bookShop=ioc.getBean(BookShopList.class);
	}

	public void test1() {
		System.out.println(bookShopDaoImpl.findBookPriceByIsbn("1002"));
	}

	public void test2() {
		bookShopDaoImpl.updateBookStock("1001");
	}


	public void test3() {
		bookShopDaoImpl.updateUserAccount("楊楓述", 28);
	}
	public void test4(){
		bookShopServiceImpl.purchase("楊楓述", "1003");
	}
	@Test
	public void test5(){
		bookShop.purchare("楊楓述", Arrays.asList("1002","1001"));
	}
}

 

預設的情況下,@Transactional(propagation=Propagation.REQUIRES)

條件:

賬戶餘額:100元

第一本書:40元;

第二本書:70元;

結果就是,結果就是,庫存都不會變化,餘額是100;


 

預設的情況下,@Transactional(propagation=Propagation.REQUIRES)

條件:

賬戶餘額:100元

第一本書:70元;

第二本書:40元;

結果就是,結果就是,庫存都不會變化,餘額是100;


如果給設定    @Transactional(propagation=Propagation.REQUIRES_NEW)

條件:

賬戶餘額:100元

第一本書:40元;

第二本書:70元;

結果就是,第一本書的庫存減少1,餘額是60;


如果給設定    @Transactional(propagation=Propagation.REQUIRES_NEW)

條件:

賬戶餘額:100元

第一本書:70元;

第二本書:40元;

結果就是,庫存都不會變化,餘額是100;


@Transactional(propagation=Propagation.REQUIRES_NEW)的好處就是

當你執行第一個小的事務的時候,如果成功了,執行第二個,如果第二個失敗了,就會返回到第二個的最開始的地方;


 

但是如果你執行第一個小的事務都失敗了,就直接回滾到事務最開始的時候