SSM系列7_進階_聲明式事務

1 何爲事務

事務:一批數據,要麼同時成功保存到數據庫,要麼同時提交到數據庫失敗
Mybatis中需要手動操作進行commit與rollback
Spring 提供了聲明式事務處理方法

2 聲明事務的配置

2.1 應用上下文開啓事務配置

applicationContext.xml 中需要增加如下設置

2.1.1 頭部增加

在這裏插入圖片描述

xmlns:tx="http://www.springframework.org/schema/tx"
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd

2.1.2 增加bean

注意:ref="dataSource"這裏引用的是你自己項目裏的數據源,數據源id是什麼這裏就寫什麼
在這裏插入圖片描述

<!--事務管理器transactionManager提供了聲明式事務的支持,在程序成功提交,拋出"運行時異常"時進行回滾-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
</bean>
<!--開啓註解形式的聲明式事務-->
<tx:annotation-driven transaction-manager="transactionManager"/>

3 聲明式事務如何使用

3.1 示例

比如說要初始化多條數據,要求插入時必須全部成功,或者全部失敗
準備好各個層所用的方法

3.1.1 mapper xml層

在這裏插入圖片描述

<insert id="insert" parameterType="com.zhangyx.ssm.entity.Goods">
        INSERT INTO `babytun`.`t_goods`(`title`, `sub_title`, `original_cost`, `current_price`, `discount`, `is_free_delivery`, `category_id`)
        VALUES (#{goods.title}, #{goods.subTitle}, #{goods.originalCost}, #{goods.currentPrice}, #{goods.discount}, #{goods.isFreeDelivery}, #{goods.categoryId})
        <selectKey resultType="int" keyProperty="goodsId" order="AFTER">
            select last_insert_id()
        </selectKey>
</insert>

3.1.2 mapper class 層

int insert(Goods goods);

3.1.3 Service層

//初始化十條數據
public void initGoods(){
	for (int i =0;i < 10 ;i++){
	Goods goods = new Goods();
	goods.setCategoryId(i);
	goods.setCurrentPrice(10f*2);
	goods.setDiscount(10f);
	goods.setIsFreeDelivery(i);
	goods.setOriginalCost(20f);
	goods.setSubTitle("模擬初始化數據");
	goods.setTitle("模擬初始化數據");
	goodsMapper.insert(goods);
	}
}

3.1.4 測試

是寫測試還是網頁調測試自己選擇
如果在i=3的時候,程序報錯了,這裏模擬程序出現異常,代碼加入

if(i==3){
    throw new RuntimeException(“RuntimeException”);
}

模擬程序出錯

//初始化十條數據
public void initGoods(){
	for (int i =0;i < 10 ;i++){
	if(i==3){
	    throw new RuntimeException(“RuntimeException”);
	}
	Goods goods = new Goods();
	goods.setCategoryId(i);
	goods.setCurrentPrice(10f*2);
	goods.setDiscount(10f);
	goods.setIsFreeDelivery(i);
	goods.setOriginalCost(20f);
	goods.setSubTitle("模擬初始化數據");
	goods.setTitle("模擬初始化數據");
	goodsMapper.insert(goods);
	}
}

頁面請求報如下錯
在這裏插入圖片描述
我們看一下數據庫數據
在這裏插入圖片描述
看到結果,只插入了三條數據,如果這是銀行轉賬,豈不是很危險
所以這個時候就用到了事務,Spring爲我們提供了聲明式事務,不用再用Mybatis的手動rollback操作
一般聲明式事務在service層使用,直接使用在類上或者方法上,在方法上只在此方法內起作用,在類上使用則該類內的方法全部開啓事務

3.2 方法上使用

在這裏插入圖片描述

3.3 類上使用

在這裏插入圖片描述

3.4 測試

程序報錯,並且自動進行了回滾,數據也沒有插入到數據庫,測試成功
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

4 設置不使用事務

如果事務放到了類上,但是我們有類中有查詢方法,查詢方法是不需要使用事務的,可以使用propagation = Propagation.NOT_SUPPORTED設置不使用事務,並且設置爲只讀的readOnly=true
在這裏插入圖片描述

5 事務作用域

上面我們使用了throw new RuntimeException()異常模擬了,程序出現異常的情況,如果程序不是出現了這個異常,而是出現了其他的異常呢,例如說拋出了ParseException(“”,1),我們來測試看一下
在這裏插入圖片描述
我們看到雖然異常拋出了,但是也有數據數據也進入了數據庫
在這裏插入圖片描述
在這裏插入圖片描述
那麼我們可以知道,@Transactionnal只對 運行時異常(RuntimeException)起作用,那麼如果出現別的問題應該怎麼辦呢,此時只需要指定此註解起作用的類@Transactional(rollbackFor = Exception.class)即可

6 指定rollbackFor

指定rollbackFor纔是此註解的真正用法
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章