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才是此注解的真正用法
在这里插入图片描述

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