美文网首页
6 事务操作

6 事务操作

作者: ca8519be679b | 来源:发表于2020-07-13 11:04 被阅读0次

事务概念

事务:数据库操作最基本单元,要么都成功,如果有一个失败,就是都失败

典型场景:银行转账,A给B转账,A钱变少,B钱变多,如果A转账过程出错,则B钱不会变多,A不会变少

四大特性:ACID

原子性:就是要么都成功,有一个失败,就全部失败,不做操作

一致性:一个状态到另一个状态必须一致的,如A没给B转成,2人前都不动,或者转成A少的数目和B增加数目一致,而不能是A失败不变,B增加或A减少,B不变

隔离性:数据库并发操作,事务间不能相互影响

持久性:修改操作一旦提交,数据库数据就发生对应变化(而不是没反应)

事务环境搭建(代码搭建)

1

JavaEE常见3层,web页面层,service业务逻辑层,dao数据库操作层,如上图,我们为了实现事务环境搭建,关心的是后2个层,其中Dao不考虑业务逻辑,只关心和数据库有关的操作,如转账,修改金额,而service层则是具体实现A少钱,B多钱的过程

2

我们使用可视化工具给user_db下创建表t_account,设置3个字段id,username,money

3

表里创建2条数据,这里我用的是MySQL workbench,记得修改要点apply应用提交,

4

可以查到数据确实创建了

然后就是创建Service类,UserDao,service注入UserDao,UserDao注入JdbcTemplate对象,JdbcTemplate注入DataSource,这个我们上节课也做过类似的

5

之前的xml就是创建数据库连接池和配置jdbcTemplate对象,这个xml文件不用动,我们删掉之前的测试类,service,dao先关

6

UserService类,注解创建对象,并自动装配Dao对象

7 8

UserDao和其实现类,注解创建对象,并自动装配jdbcTemplate对象

9

我们定义方法,修改money

10

实现类如上,我们使用update方法,不记得怎么用看上节课,

11

Service类里定义转账方法,底层是调用dao的方法

12

如上,实现了转账100,当然这是正常情况下,

13

如上,比如银行操作时,发生断电了,我们使用/0实现故障,操作前将账户设为1000,1000

14

结果就变成报错外,数据lucy少了100,而Mary没变,总共丢了100,肯定是不对的

这就需要使用事务来进行处理,先说下大致逻辑

如果代码编程:我们使用trycatch结构捕获异常,try里先开启事务,然后数据库操作,最后结尾没有异常就提交事务,catch捕获到异常,里面进行事务的回滚操作。但是spring5给我们提供了更方便的事务管理相关的封装

spring事务管理介绍

之前我们之前说过JavaEE的三个层,我们事务管理一般在业务逻辑层里

spring进行事务管理操作一般有2种方式:编程式和声明式(常用后者)

我开始说的try catch finally就是编程式事务操作


对于声明式事务管理,有2种实现方式,即熟悉的xml配置和注解配置(当然还是注解最常用),spring使用事务管理,其底层其实就是AOP

spring对事务有专门的接口,针对不同的框架,有专门的实现类

15

如上图,接口就是PlatformTransactionManager,看结构可以看到子接口和实现类,其中,使用JdbcTemplate和Mybatis都是使用DataSourceTransactionManager,如果是使用Hibernate,则使用HibernateTransactionManager

声明式事务管理(基于注解)

步骤:1 配置文件创建事务管理器实现类对象bean,这个没啥说的,如下图

16 17

我们查看源码可以看到其有DataSource属性,我们需要给其注入数据源属性,xml里数据源已经制定好了

18

2.导入aop和tx名称空间,因为事务是依赖aop的,如下图,相信我们已经回来

19

3 开启事务注解,此处还是在xml里

20

使用tx空间的annotation-driven标签,指定事务管理为我们之前创建的对象

21

4给Service添加注解@Transactional(给类添加,则类所有方法都进行事务管理,也可以给方法添加,使指定方法事务管理),如上

22

最后运行测试类,我们先把金额改回1000,1000然后运行带/0的代码,可以看到虽然报错,但是账户并没有变化

基于注解配置事务的参数

刚才我们使用了@Transactional注解,其实是可以传入参数的

23

我们给注解加上括号,可以看到其可以传入很多参数,我们重点关辛苦其中红框的6个,分别是事务传播行为,事务隔离,超时,只读,回滚和不回滚。下面我们分别对6个属性逐一解释

propagation事务传播行为

事务传播官方解释:多事务方法进行调用,过程中如何进行事务管理

什么是事务呢,对数据库进行添加修改删除等操作(使事务发生变化,不算查询)就是事务

24

上面一张图方便我们理解传播行为,我们定义2个方法,add和update,其中add内部调用了update,我们给add方法加了事务,而update没有事务,这是一种情况,还有一种update有事务,调用他的add没事务,另一种,还有2个都有事务,如何管理这些情况的事务就是事务传播行为

25

spring对于事务传播,定义了7种行为,如上图

REQUIRED,图中解释比较官方,我们还是以add和update为例,比如我们add有事务,而update没有事务,则update操作依据与add的事务。如果add事务终止(视频上说没有事务,,觉得这不太可能),则启动一个事务执行(是spring里的默认设置)

REQUIRED_NEW,不管add是否有事务运行,都新建一个事务(之前有的事务会被挂起)

其他几个可能不是特别常用

26

我们给加上propagation属性如上,idea等号右侧输入REQUIRED,自动补全

隔离级别

我们知道事务有隔离性,即多事务操作不能互相影响

多事务有3个读问题:脏读,不可重复读,虚读(也叫幻读)

脏读:一个未提交的事务读取到了另一个未提交事务的数据

27

上图来说明脏读,比如2个人都访问1条记录,都开启了事务,如果没有隔离,A事务要给钱-100,B要给钱变成60000,如果B修改60000了,可能A读到60000再-100,但是B没有提交,B回滚了,A就出现问题了,注意2个都是未提交

不可重复读:一个未提交事务访问已提交修改的事务的数据

28

如上图,2个人分别开启事务A,B,A获得金额5000,B也是,但是B想修改把钱变成了900,并提交了事务,而A再进行事务读取时,发现已经变化了

当然脏读是质量问题,而不可重复度是一种现象

虚读:一个未提交事务访问另一个事务已提交添加的数据

29

spring配置的隔离级别属性如上,我们可以看到不同隔离级别的几种读现象出现

30

添加了隔离属性的注解如上

其他事务属性

1超时 timeout,如果事务一定时间内未提交,则进行回滚,默认-1,即不超时,设置指定值单位为秒

2 readOnly,设置是否只读,默认false,设置为true,则只能查询,不能修改添加删除

3 rollBackFor回滚,设置哪些异常进行回滚,等号右侧为异常类名.class

4 noRollBackFor不回滚,设置哪些异常不回滚,赋值同上

基于xml进行声明式事务管理

虽然注解是最常用的,这里仅体现xml实现方式,分3步:1配置事务管理器,2配置通知,3配置切入点和切面。2,3为aop部分,我们之前讲过,我们增强的部分叫做通知,切入点就是把事务加载到哪个方法,而切面就是把事务加载的过程进行体现

31

我们把之前的xml拷贝一份叫bean2.xml,并把<tx:annotation-driven transaction-manager="tm"></tx:annotation-driven>开启事务注解删掉,保留bean标签,因为这个标签就是创建事务管理器

32

接下来配置通知,我们使用tx:advice标签,给其起个id,里面在tx:attributes标签里添加方法,我们可以给其传入方法名,也可以像下一行使用*,表示对所有user2开头的方法增强,我们还可以给标签其他参数,就可以看到我们事务的几个属性啦

33

然后就是创建切入点,还是使用aop:config标签,然后内部使用aop:pointcut,expresssion传入切入点表达式

34

然后是配置切面,我们学aop是使用aop:aspect,这里使用aop:advisor,pointcut_ref就是传入我们的切入点id,然后advice-ref传入我们的通知id

35

为了运行测试把service里注解给注释了

36

然后修改测试类注意是bean2.xml,本以为你我运行会和视频一样OK的,但是我报错了,这里提示创建bean对象异常,我仔细排查了半天终于找到了结果,要给通知添加事务管理器关联

37

修改后正常,只显示/0异常,我猜测可能默认是设置id为如下图,idea提示的,而我起名tm,还真他妈。。

38 39

运行结果正常

使用完全注解进行事务操作

我们之前使用注解还是用了xml文件,这次我们只通过注解实现事务操作

40

我们之前的xml文件是这样的

首先完全注解开发,需要给创建配置类替代xml文件

41

如上图,我们创建config包,创建配置类TxConfig,然后使用几个注解,这里算是只是回顾了@Configuration声明此类为配置类,@ComponentScan开启组件扫描,我们在com.demo.spring5下面扫描即可,@EnableTransactionManagement 开启事务管理。接下来就是给配置类里注入属性了,像数据库连接池等等

42

我们xml里是使用bean标签,我们这里使用@Bean注解,然后对象设置返回数据源,类型参照xml创建对象,里面我们new这个类即可,其中几个属性通过对象的set方法,参照xml把属性设置过来,最后返回数据源,如上,接下来,参照之前的文件我们需要创建JdbcTemplate对象,还是如法炮制

43

如上,其中模板对象需要注入数据源,我们可以通过上个方法的返回值创建,但是没必要,因为默认会调用方法,但是因为单例,IOC容器只创建一次,我们直接使传入数据源参数,让spring按类型自动装配即可

44

创建事务管理器,如上,没什么说的,至此,我们的配置类就把xml文件完全替代了

45

我们把Service里的注释取消,恢复@Transactional注解

46

测试类里变化的就是需要使用注解的上下文,参数传入配置类的class

47

就在我兴致冲冲的去运行,又TM报错啦,NND,提示是字符编码问题,setUrl里传入的字符串有问题,后来将&amp;改成&即可,因为xml里是特殊语法

48

然后还没完,改完了提示事务隔离界别不支持None,即设置REPEATABLE_READ不行,,

49

最后改成default,只有/0错误,,终于完事

50

验证如下,实际使用中,完全注解是王道,xml不用最好

相关文章

  • 6 事务操作

    事务概念 事务:数据库操作最基本单元,要么都成功,如果有一个失败,就是都失败 典型场景:银行转账,A给B转账,A钱...

  • mysql 事务

    事务的操作 1、创建一张测试表 2、开启事务 3、设置保存点 4、执行dml操作 5、回退到a保存点 6、comm...

  • 【PHP】让新人快速理解ThinkPHP6中的事务操作

    事务操作对很多新人来说,可能有点陌生,即使看了ThinkPHP6官方手册中事务操作的部分,也仍然不知所解。 下面就...

  • 事务、MySQL与Python交互、Python 中操作 MyS

    1、事务 事务操作分两种:自动事务(默认)、手动事务 手动事务的操作流程 开启事务:start transacti...

  • MySQL数据库的事务transaction

    事务操作分两种:自动事务(默认)、手动事务 手动事务的操作流程 开启事务:start transaction; 进...

  • Spring事务隔离和事务传播

    事务:事务程序中一系列的操作,所有操作必须成功完成,否则每个操作做的更改会被撤销。 事务特性:原子...

  • Spring事务管理

    事务回顾 事务指的是逻辑上的一组操作,这组操作要么全部成功,要么全部失败。事务操作能够保证数据操作的安全性。 以一...

  • 什么是事务、事务特性、事务隔离级别、spring事务传播特性

    引用地址 什么是事务?事务是程序中一系列严密的操作,所有操作必须成功完成,否则每个操作所做的操作将会撤销,这是事务...

  • Hibernate中的事务与并发

    Hibernate中的事务与并发 事务相关的概念 什么是事务事务就是逻辑上的一组操作,组成事务的各个执行单元,操作...

  • 事务操作

    前提是储存引擎必须是innodb 事务操作原理? 在开启事务之后,所有的操作都会先写入临时日志文件,没有问题的话,...

网友评论

      本文标题:6 事务操作

      本文链接:https://www.haomeiwen.com/subject/rrzqqktx.html