基于注解的声明式事务

基于注解的声明式事务

准备工作:

在数据库中创建两张表,代码如下所示:

CREATE TABLE `t_book` (
`book_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`book_name` varchar(20) DEFAULT NULL COMMENT '图书名称',
`price` int(11) DEFAULT NULL COMMENT '价格',
`stock` int(10) unsigned DEFAULT NULL COMMENT '库存(无符号)',
PRIMARY KEY (`book_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
insert into `t_book`(`book_id`,`book_name`,`price`,`stock`) values (1,'斗破苍
穹',80,100),(2,'斗罗大陆',50,100);
CREATE TABLE `t_user` (
`user_id` int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
`username` varchar(20) DEFAULT NULL COMMENT '用户名',
`balance` int(10) unsigned DEFAULT NULL COMMENT '余额(无符号)',
PRIMARY KEY (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
insert into `t_user`(`user_id`,`username`,`balance`) values (1,'admin',50);

结果如下所示:
基于注解的声明式事务_第1张图片

基于注解的声明式事务_第2张图片 

 事务实现功能:

声明式事务中不需要手动创建事务的切面和通知,因为在当前提供的spring中提供有事务管理的切面和通知,叫事务管理器

创建组件:控制层、业务层,持久层中的类和接口

基于注解的声明式事务_第3张图片

 在持久层中的接口中添加根据图书id查询图书的价格和更新图书的库存和更新用户的余额的抽象方法

基于注解的声明式事务_第4张图片

 在持久层的Dao的方法中实现接口,并实现接口中的方法

基于注解的声明式事务_第5张图片

 在业务层中添加买书的业务的接口

基于注解的声明式事务_第6张图片

在业务层中的类中实现业务层的接口 

基于注解的声明式事务_第7张图片

 在控制层中的类中添加方法去调用业务层的类去实现买书的业务

基于注解的声明式事务_第8张图片

 在存放配置文件的目录下创建配置文件

基于注解的声明式事务_第9张图片

 在配置文件中进行扫描组件、配置事务管理器、开启事务的注解驱动;在文件tx-annotation.xml文件中添加如下所示:

基于注解的声明式事务_第10张图片

提示:

此处的dataSource数据源在之前中已经进行添加:若未添加可以自行添加,如下内容即可:

基于注解的声明式事务_第11张图片

 添加测试类:

基于注解的声明式事务_第12张图片

在测试类中添加测试方法: 

基于注解的声明式事务_第13张图片

由于出现了再购买中的钱只有50不能购买80元的书,所有有逻辑异常,由于在上述的业务层的实现类中已经添加了@Transactional的注解,对sql进行了事务的管理 

测试结果如下所示:

基于注解的声明式事务_第14张图片

注意:

现象是无论如何进行操作都无法更改书的数量

因为该三种方法已经被事务进行管理,必须如下三者方法都满足且进行才能进行执行,否则回滚

 基于注解的声明式事务_第15张图片

只读、超时、回滚策略:

介绍:事务属性:只读

对一个查询操作来说,若把他设置为只读,就能够明确告诉数据库,这个操作不涉及写操作。这样数据库就能够针对查询操作来进行优化

使用方式:

在事务管理的注解上添加readOnly 并设置为true
基于注解的声明式事务_第16张图片

 注意:

对增删改操作设置只读会抛出如下异常

测试结果如下所示:

事务属性:超时

介绍:
事务在执行过程中,有可能因为遇到某些问题,导致程序卡住,从而长时间占用数据库资源。而长时间占用资源,大概率是因为程序运行出现了问题(可能是java程序或MySQL数据库或网络连接等出现问题)

此时这个很可能出问题的程序应该被回滚,撤销它已做的操作,事务结束,把资源让出来,让其他正常程序可以执行;即超时回滚,释放资源

使用方法:
如果5秒钟事务未执行完,则进行休眠

基于注解的声明式事务_第17张图片

 测试结果如下所示:

强制回滚并抛出异常

 事务属性:回滚策略

介绍:
声明式事务默认只针对运行时异常回滚,编译时异常不回滚,可以通过@Transactional中相关属性设置回滚策略

1.rollbackFor属性:需要设置一个Class类型的对象

2.rollbackForClassName属性:需要设置一个字符串类型的全类名

3.noRollbackFor属性:需要设置一个Class类型的对象

4.rollbackFor属性:需要设置一个字符串类型的全类名

默认情况下:所有的运行时异常都会造成回滚

回滚策略是指:当遇到某种异常后进行回滚某种异常后不回滚

使用方法:

观察结果:虽然购买图书功能中出现了数学运算异常(ArithmeticException),但是设置的回滚策略是当出现ArithmeticException不发生回滚,因此购买图书的操作正常执行

基于注解的声明式事务_第18张图片

 将数据库中的表中的用户金额设置为100

基于注解的声明式事务_第19张图片

 测试结果如下所示:

书的数量较少了1本

基于注解的声明式事务_第20张图片

 隔离级别

事务属性:隔离级别

介绍:

数据库系统必须具有隔离并发运行各个事务的能力,使他们不会相互影响,避免各种并发问题。一个事务与其他事务隔离的程度称为隔离级别,SQL标准中规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性越弱

隔离级别一共有4种:

        1.读未提交:READ UNCOMMITTED

                允许Transactional01读取Transactional02未提交的修改

        2.读已提交 :READ COMMITTED

                要求Transactional01只能读取Transactional02已提交的修改

        3.可重复读:REPEATABLE READ

                确保Transactional01可以多次从一个字段中读取相同的值,即Transactional01执行期间禁止其他事务对这个字段进行更新

        4.串行化:SERIALIZABLE

                确保Transactional01可以多次从一个表中读取到相同的行,在Transactional01执行期间,禁止其他是因为对这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能较低

注意:

脏读:读出来的数据没有意义

MySQL默认为可重复读,并且避免了幻读的情况

基于注解的声明式事务_第21张图片

基于注解的声明式事务_第22张图片 

使用方式:
通过声明式事务来设置隔离级别:

    基于注解的声明式事务_第23张图片

传播行为:

事务属性:事务传播行为

介绍:

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

使用方法:

可以通过@Transactional中的propagation属性设置事务传播行为,可以通过修改BookServiceImpl中buyBook()上,注解@Transaction的propagation属性。

@Transactional(propagation = Propagation.REQUIRED),默认情况,表示如果当前线程上有已经开启的事务可用,那么就在这个事务上中运行。经过观察,购买图书的方法buyBook()在checkout()中被调用,checkout()上有事务注解,因此在此事务注解中执行。所购买的两本图书的价格为80和50,而用户的余额为100,因此在购买2本图书时余额不足则失败,导致整个checkout()回滚,即只要有一本买不了则都不能购买。

@Transactional(propagation = Propagation.REQUIRES_NEW),表示不管当前线程上是否有已经开启的事务,都要开启新事务。同样的场景,每次购买图书都是在buyBook()的事务中执行,因此第一本图书购买成功,事务结束,第二本图书购买失败,只在第二次的buyBook()中回滚,够买第一本图书不受影响,即能买几本就买几本

新建一个CheckoutService的接口和接口的实现类来完成结账的功能

基于注解的声明式事务_第24张图片

在接口中添加需要实现的功能的抽象方法 

基于注解的声明式事务_第25张图片

在实现类中实现接口并添加事务管理的注解并实现在接口中的方法 

基于注解的声明式事务_第26张图片

在控制层的BookController的类中添加结账所调用的方法并且自动装配CheckoutService 

基于注解的声明式事务_第27张图片

在业务层的BookService的类中设置事务传播行为 

基于注解的声明式事务_第28张图片

添加测试的方法: 

基于注解的声明式事务_第29张图片

测试结果如下所示: 

基于注解的声明式事务_第30张图片基于注解的声明式事务_第31张图片

你可能感兴趣的:(Spring,java,spring,开发语言)