6 事务操作

事务概念

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

典型场景:银行转账,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不用最好

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,366评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,521评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,689评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,925评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,942评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,727评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,447评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,349评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,820评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,990评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,127评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,812评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,471评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,017评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,142评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,388评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,066评论 2 355