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)的好處就是
當你執行第一個小的事務的時候,如果成功了,執行第二個,如果第二個失敗了,就會返回到第二個的最開始的地方;
但是如果你執行第一個小的事務都失敗了,就直接回滾到事務最開始的時候