记一次 Spring 事务配置踩坑记

问题描述:(SpringBoot + MyBatisPlus)

业务逻辑伪代码如下。理论上,插入数据 t1 后,xxService.getXxx() 方法的查询条件会不满足,会查询不到数据。结果事与愿违,后一次的查询,居然查到了数据。

void saveXxx(){
 xxService.getXxx(); // 查到一条数据 data1
 xxService.insert(); // 插入一条数据 t1
 xxService.getXxx(); // 查到一条数据 data1
}

分析过程:

抛弃业务逻辑,在一个新的 service 中写了一个最简单的测试,查询 --> 插入 --> 查询。为了保证两者具有可比性,sql 都从原 Mapper 中拷贝过去。但是依然重现不了问题。神奇的是出现了如下的情况:

@Transactional
void testMyBatis(){
 yyService.getYyy(); // 查到一条数据 data1
 yyService.insert(); // 插入一条数据 t1
 yyService.getYyy(); // 查不到数据
 xxService.getXxx(); // 查到一条数据 data1
}

理论上,yyService.getYyy() 与 xxService.getXxx() 应该都查不到数据才对,结果只有 xxService.getXxx() 能查到。

开始怀疑事务的问题,是不是 xxService.getXxx() 新开启了一个事务去查询,只有这样,xxService.getXxx() 的查询条件才不受当前事务插入的数据所影响。

检查项目中的事务配置,除了配置了注解式事务外,还有如下的声明式事务配置:

@Bean
public TransactionInterceptor txAdvice() {
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
readOnlyTx.setReadOnly(true);
readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED );
RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
requiredTx.setRollbackRules(Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
requiredTx.setTimeout(TX_METHOD_TIMEOUT);
Map<String, TransactionAttribute> txMap = new HashMap<>();
txMap.put("add*", requiredTx);
txMap.put("save*", requiredTx);
txMap.put("insert*", requiredTx);
txMap.put("update*", requiredTx);
txMap.put("delete*", requiredTx);
txMap.put("get*", readOnlyTx);
txMap.put("query*", readOnlyTx);
source.setNameMap( txMap );
TransactionInterceptor txAdvice = new TransactionInterceptor(transactionManager, source);
return txAdvice;
}

就是这一行配置搞的鬼:readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED ); get*开头的方法都加了只读事务,而只读事务是以非事务方式运行,如果当前存在事务,则把当前事务挂起。

这样就解释了为什么 xxService.getXxx() 方法能够查到数据了,它是在当前事务之外查询的数据。

解决办法:

将 readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED ); 去掉。

附:还是使用注解式事务吧 ^_^

记一次 Spring 事务配置踩坑记的更多相关文章

  1. spring事务配置的坑

    基于 <tx> 命名空间的声明式事务管理 前面两种声明式事务配置方式奠定了 Spring 声明式事务管理的基石.在此基础上,Spring 2.x 引入了 <tx> 命名空间,结 ...

  2. Gitlab Jenkins WebHook 持续集成配置踩坑记

    Jenkins相关介绍 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 目的 配置Gitla ...

  3. react中的路由配置踩坑记

    react 路由配置中,如果根路由(/)匹配一个组件,另一个路由(/list)在进行匹配的时候也会匹配到根路由(/),即在 /list 页面展示的时候 / 页面总是展示在上方. 此时如果想进行严格匹配 ...

  4. vscode 配置踩坑记

    vscode-easy-less 遇到问题最好的解决方式是看官网文档,切记!!! 在web开发当中,经常会写less然后编译成css,当然在VS Code当中也有这样的插件(EasyLess), 但是 ...

  5. Spring @Transactional踩坑记

    @Transactional踩坑记 总述 ​ Spring在1.2引入@Transactional注解, 该注解的引入使得我们可以简单地通过在方法或者类上添加@Transactional注解,实现事务 ...

  6. Spark踩坑记——Spark Streaming+Kafka

    [TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...

  7. Spark踩坑记——数据库(Hbase+Mysql)

    [TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...

  8. Spark踩坑记——共享变量

    [TOC] 前言 Spark踩坑记--初试 Spark踩坑记--数据库(Hbase+Mysql) Spark踩坑记--Spark Streaming+kafka应用及调优 在前面总结的几篇spark踩 ...

  9. Spark踩坑记——从RDD看集群调度

    [TOC] 前言 在Spark的使用中,性能的调优配置过程中,查阅了很多资料,之前自己总结过两篇小博文Spark踩坑记--初试和Spark踩坑记--数据库(Hbase+Mysql),第一篇概况的归纳了 ...

随机推荐

  1. 喵哈哈村的魔法考试 Round #9 (Div.2) 题解

    A题 喵哈哈村的数据筛选游戏 题解:这道题签到题,拿个数组记录一下这个数是否出现过即可. #include<bits/stdc++.h> using namespace std; cons ...

  2. C# Request 获取Url

    1.获取页面,HttpContext.Current.Request也是Request //获取当前页面url string myurl = System.Web.HttpContext.Curren ...

  3. mongodb crud

    //添加数据 db.users.insert({,"gender":"男"}); db.users.insert({"name":" ...

  4. c++以代理的方式来实现接口化编程

      假如你项目代码本身已经实现了很多的实体类,但并未采用接口,可以考虑以这种方式来实现接口化编程 struct ITest { virtual void Test()=0; }; class CTes ...

  5. oracle io 等待图解

  6. 将控件画成圆角的效果(Delphi)

    最近在做一个Delphi的项目,常常要设计软件的界面,需要将控件画成圆角矩形.在Delphi中将控件画成圆角效果,可使用CreateRoundRectRgn函数.在此写了一个通用的函数,只要在用到改变 ...

  7. Layout Inflation :Unconditional layout, inflation from view adapter

    Layout inflation在Android上下文环境下转换XML文件成View结构对象的时候需要用到. LayoutInflater这个对象在Android的SDK中很常见,但是你绝对没想到竟然 ...

  8. javascript中new Date()的浏览器兼容性问题

    正确的做法: var time1 = (timestart+' 00:00:00').toString(); var time2 = (timeend+' 23:59:59').toString(); ...

  9. SharePoint Online 自定义Modern UI表单

    前言 用过SharePoint Online 版本的朋友们,应该很熟悉SharePoint为我们带来的Modern UI,而这个页面的订制,也跟原来的表单定制方式不同了,而且更加简单了. 而且,试了一 ...

  10. 从安装node js到构建一个vue并启动它

    1.安装node js 下载地址:http://nodejs.cn/download/2.安装完成后运行Node.js command prompt(node -v查看安装版本) 3.安装npm(由于 ...