深入了解Spring的事务传播机制_第1页
深入了解Spring的事务传播机制_第2页
深入了解Spring的事务传播机制_第3页
深入了解Spring的事务传播机制_第4页
深入了解Spring的事务传播机制_第5页
已阅读5页,还剩4页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第深入了解Spring的事务传播机制目录Spring事务传播机制有哪些?事务传播机制使用与演示REQUIRED使用演示REQUIRED_NEW使用演示NESTED使用演示总结Spring事务传播机制是指,包含多个事务的方法在相互调用时,事务是如何在这些方法间传播的。

既然是事务传播,所以事务的数量应该在两个或两个以上,Spring事务传播机制的诞生是为了规定多个事务在传播过程中的行为的。比如方法A开启了事务,而在执行过程中又调用了开启事务的B方法,那么B方法的事务是应该加入到A事务当中呢?还是两个事务相互执行互不影响,又或者是将B事务嵌套到A事务中执行呢?所以这个时候就需要一个机制来规定和约束这两个事务的行为,这就是Spring事务传播机制所解决的问题。

Spring事务传播机制有哪些?

Spring事务传播机制可使用@Transactional(propagation=Propagation.REQUIRED)来定义,Spring事务传播机制的级别包含以下7种:

Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。Propagation.SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。Propagation.MANDATORY:(mandatory:强制性)如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。Propagation.REQUIRES_NEW:表示创建一个新的事务,如果当前存在事务,则把当前事务挂起。也就是说不管外部方法是否开启事务,Propagation.REQUIRES_NEW修饰的内部方法会新开启自己的事务,且开启的事务相互独立,互不干扰。Propagation.NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。Propagation.NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。Propagation.NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于PROPAGATION_REQUIRED。

以上7种传播机制,可根据是否支持当前事务的维度分为以下3类:

看到这里,有人可能会说:说了这么多,我也看不懂啊,即使看懂了,我也记不住啊?这要咋整?

没关系,接下来我们用一个例子,来说明这3类事务传播机制的区别。

以情侣之间是否要买房为例,我们将以上3类事务传播机制可以看作是恋爱中的3类女生类型:

普通型强势型懂事型

这三类女生如下图所示:

支持当前事务的女生,这里的事务指的是房子,它分为3种(普通型女生):

Propagation.REQUIRED(需要有房子):有房子了咱们一起住,没房子了咱们一起赚钱买房子。Propagation.SUPPORTS(可以有房子):有房子了就一起住,没房子了咱们就一起租房子。Propagation.MANDATORY(强制有房子):有房子了就一起住,没房子了就分手。

不支持当前事务的女生也分为3种(强势型或者叫事业型):

Propagation.REQUIRES_NEW:不要你的房子,必须一起赚钱买房子。Propagation.NOT_SUPPORTED:不要你的房子,必须一起租房子。Propagation.NEVER:必须一起租房子,你有房子就分手。

最后一种是嵌套性事务Propagation.NESTED,它属于懂事型女友,如果有房子了就以房子为基础做点小生意,卖个花生、水果啥的,如果买卖成了,那就继续发展;如果失败了,至少还有房子;如果没房子也没关系,一起赚钱买房子。

事务传播机制使用与演示

接下来我们演示一下事务传播机制的使用,以下面3个最典型的事务传播级别为例:

支持当前事务的REQUIRED;不支持当前事务的REQUIRES_NEW;嵌套事务NESTED。

下来我们分别来看。

事务传播机制的示例,需要用到以下两张表:

--用户表

CREATETABLE`user`(

`id`int(11)NOTNULLAUTO_INCREMENT,

`name`varchar(255)COLLATEutf8mb4_binDEFAULTNULL,

`password`varchar(255)COLLATEutf8mb4_binDEFAULTNULL,

`createtime`datetimeDEFAULTCURRENT_TIMESTAMP,

PRIMARYKEY(`id`)USINGBTREE

)ENGINE=InnoDBAUTO_INCREMENT=6DEFAULTCHARSET=utf8mb4COLLATE=utf8mb4_binROW_FORMAT=DYNAMIC;

--日志表

CREATETABLE`log`(

`id`int(11)NOTNULLAUTO_INCREMENT,

`content`textNULL,

PRIMARYKEY(`id`)

)ENGINE=InnoDBDEFAULTCHARSET=utf8mb4COLLATE=utf8mb4_bin;

创建一个SpringBoot项目,核心业务代码有3个:UserController、UserServcie以及LogService。在UserController里面调用UserService添加用户,并调用LogService添加日志。

REQUIRED使用演示

REQUIRED支持当前事务。

UserController实现代码如下,其中save方法开启了事务:

@RestController

publicclassUserController{

@Resource

privateUserServiceuserService;

@Resource

privateLogServicelogService;

@RequestMapping("/save")

@Transactional

publicObjectsave(Useruser){

//插入用户操作

userService.save(user);

//插入日志

logService.saveLog("用户插入:"+user.getName());

returntrue;

UserService实现代码如下:

@Service

publicclassUserService{

@Resource

privateUserMapperuserMapper;

@Transactional(propagation=Propagation.REQUIRED)

publicintsave(Useruser){

returnuserMapper.save(user);

LogService实现代码如下:

@Service

publicclassLogService{

@Resource

privateLogMapperlogMapper;

@Transactional(propagation=Propagation.REQUIRED)

publicintsaveLog(Stringcontent){

//出现异常

inti=10/0;

returnlogMapper.saveLog(content);

执行结果:程序报错,两张表中都没有插入任何数据。

执行流程描述:

首先UserService中的添加用户方法正常执行完成。LogService保存日志程序报错,因为使用的是UserController中的全局事务,所以整个事务回滚,步骤1中的操作也跟着回滚。所以数据库中没有添加任何数据。

REQUIRED_NEW使用演示

REQUIRED_NEW不支持当前事务。

UserController实现代码:

@RequestMapping("/save")

@Transactional

publicObjectsave(Useruser){

//插入用户操作

userService.save(user);

//插入日志

logService.saveLog("用户插入:"+user.getName());

returntrue;

UserService实现代码:

@Service

publicclassUserService{

@Resource

privateUserMapperuserMapper;

@Transactional(propagation=Propagation.REQUIRES_NEW)

publicintsave(Useruser){

System.out.println("执行save方法.");

returnuserMapper.save(user);

LogService实现代码:

@Service

publicclassLogService{

@Resource

privateLogMapperlogMapper;

@Transactional(propagation=Propagation.REQUIRES_NEW)

publicintsaveLog(Stringcontent){

//出现异常

inti=10/0;

returnlogMapper.saveLog(content);

程序执行结果:

User表中成功添加了一条用户数据,Log表执行失败,没有加入任何数据,但它并没有影响到UserController中的事务执行。

通过以上结果可以看出:LogService中使用的是单独的事务,虽然LogService中的事务执行失败了,但并没有影响UserController和UserService中的事务。

NESTED使用演示

NESTED是嵌套事务。

UserController实现代码如下:

@RequestMapping("/save")

@Transactional

publicObjectsave(Useruser){

//插入用户操作

userService.save(user);

returntrue;

UserService实现代码如下:

@Transactional(propagation=Propagation.NESTED)

publicintsave(Useruser){

intresult=userMapper.save(user);

System.out.println("执行save方法.");

//插入日志

logService.saveLog("用户插入:"+user.getName());

returnresult;

LogService实现代码如下:

@Transactional(propagation=Propagation.NESTED)

publicintsaveLog(Stringcontent){

//出现异常

inti=10/0;

returnlogMapper.saveLog(content);

最终执行结果,用户表和日志表都没有添加任何数据。

执行流程描述:

UserController中调用了UserService的添加用户方法,UserService使用NESTED循环嵌套事务,并成功执行了添加用户的方法。UserService中调用了LogService的添加方法,LogService使用了NESTED循环嵌套事务,但在方法执行中出现的异常,因此回滚了当前事务。因为UserService使用的是嵌套事务,所以发生回滚的事务是全局的,也就是说UserSer

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论