场景: 由于在一个方法中存在多个不同业务操作   

  private void insertOrUpdateField(CompanyReport entity) {

                //计算并数据
calcReportData(entity); // 对比上季度或上年度数据,生成风险警示
raiseReportRisk(entity.getId()); // 检测并级联产生年度数据,并对比年度数据,生成风险警示
checkAndGenerateYearData(entity.getId()); } private void raiseReportRisk(String reportId){
CompanyReport report = get(reportId);
//产生问题的地方---------------------------
//若为季度数据,则找上一季度
if(report.getYear() != null && report.getQuarter() != null){
if(report.getQuarter() >1){
report.setQuarter(report.getQuarter() - 1);
} else{
report.setYear(report.getYear() - 1);
report.setQuarter(4);
} } else {
//若为年度数据,则找上一年度
report.setYear(report.getYear() - 1);
}
CompanyReport lastReport = getByPeriod(report);
if(lastReport != null){
//重置风险状态
fieldValueMapper.updateForResetRisk(reportId);
//识别风险状态
fieldValueMapper.updateForRisk(reportId, lastReport.getId());
} }
private void checkAndGenerateYearData(String reportId){ CompanyReport currentReport = get(reportId); //这里的year quarter两个值与数据库里不一致了
}

由于上面一段代码的执行顺序问题

1:生成风险警示raiseReportRisk 执行这个方法的时候  通过id查询了companyReport对象  那么这时候mybatis会将数据存储在一级缓存中   
同时将查询结果companyReposrt 中的year 与quarter修改了
2:在级联产生年度数据的时候checkAndGenerateYearData 又通过id去查询companyReport 由于第一次已经查询过了 第二次又进行了一次查询 第二次默认查询了是缓存中的数据
那么结果就是year 被修改的数据 造成了严重的不一致问题 解决方案:1:调整两个方法的执行顺序 在业务允许的情况下
2:将raiseReportRisk 中查询的companyReposrt 重新创建一个新的对象 将属性赋值过去 两个对象 修改重新创建的对象
3: 每次查询都更新查询缓存 mybatis一级缓存如何修改
一级缓存的级别设为 statement 级别的,这样每次查询结束都会清掉一级缓存


												

关于mybatis 一级缓存引发的问题的更多相关文章

  1. MyBatis 一级缓存与二级缓存

    MyBatis一级缓存 MyBatis一级缓存默认开启,一级缓存为Session级别的缓存,在执行以下操作时一级缓存会清空 1.执行session.clearCache(); 2.执行CUD操作 3. ...

  2. MyBatis一级缓存引起的无穷递归

    MyBatis一级缓存引起的无穷递归 引言: 最近在项目中参与了一个领取优惠劵的活动,当多个用户领取同一张优惠劵的时候,使用了数据库锁控制并发,起初的设想是:如果多个人同时领一张劵,第一个到达的人领取 ...

  3. mybatis一级缓存详解

    mybatis缓存分为一级缓存,二级缓存和自定义缓存.本文重点讲解一级缓存 一:前言 在介绍缓存之前,先了解下mybatis的几个核心概念: * SqlSession:代表和数据库的一次会话,向用户提 ...

  4. 0065 MyBatis一级缓存与二级缓存

    数据库中数据虽多,但访问频率却不同,有的数据1s内就会有多次访问,而有些数据几天都没人查询,这时候就可以将访问频率高的数据放到缓存中,就不用去数据库里取了,提高了效率还节约了数据库资源 MyBatis ...

  5. MyBatis 一级缓存避坑

    MyBatis 一级缓存(MyBaits 称其为 Local Cache)无法关闭,但是有两种级别可选: package org.apache.ibatis.session; /** * @autho ...

  6. MyBatis一级缓存(转载)

    <深入理解mybatis原理> MyBatis的一级缓存实现详解 及使用注意事项 http://demo.netfoucs.com/luanlouis/article/details/41 ...

  7. MyBatis 一级缓存、二级缓存全详解(一)

    目录 MyBatis 一级缓存.二级缓存全详解(一) 什么是缓存 什么是MyBatis中的缓存 MyBatis 中的一级缓存 初探一级缓存 探究一级缓存是如何失效的 一级缓存原理探究 还有其他要补充的 ...

  8. Mybatis一级缓存和二级缓存总结

    1:mybatis一级缓存:级别是session级别的,如果是同一个线程,同一个session,同一个查询条件,则只会查询数据库一次 2:mybatis二级缓存:级别是sessionfactory级别 ...

  9. Mybatis一级缓存、二级缓存详讲

    Mybatis 一级缓存.二级缓存 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 查询缓存 首先,我们先看一下这个标题“查询缓存”,那就说明跟增.删.改是没有任何关联的,只有在查询 ...

随机推荐

  1. ajax的jquery写法和原生写法

    一.ajax的简介 Ajax被认为是(Asynchronous(异步) JavaScript And Xml的缩写).现在,允许浏览器与服务器通信而无须刷新当前页面的技术都被叫做Ajax. 同步是指: ...

  2. springMvc 添加定时任务

    1.创建定时类 import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stere ...

  3. 《C++面向对象程序设计》之变量的生存期

    <C++面向对象程序设计>之变量的生存期 静态生存期 (1)全局静态生存期:在函数体外声明,作用域从声明处开始到文件结尾处结束,称其有文件作用域,相当于全局变量 . (2)局部静态生存期: ...

  4. C/C++ sort函数的用法

    sort函数的用法(#include<algorithm>) 做ACM题的时候,排序是一种经常要用到的操作.如果每次都自己写个冒泡之类的O(n^2)排序,不但程序容易超时,而且浪费宝贵的比 ...

  5. hihocoder 1109 堆优化的Prim算法

    题目链接:http://hihocoder.com/problemset/problem/1109 , 最小生成树 + 堆优化(优先队列). 可以用优先队列,也可以自己手动模拟堆,为了练手,我两种都试 ...

  6. go语言,第三方包相对路径导入包引起的问题及解决方案(goquery)

    对go语言而言,跟踪init很显然包有且仅有一次被导入的可能. 但是重复引用了goquery包,后编译出现问题 项目涉及相关目录 ├── main.go└── parse    └── parse.g ...

  7. iOS Dispatch_sync 阻塞线程的原因

    大家的知道在主队列上使用dispatch_sync(), - (void)testSyncMainThread { dispatch_queue_t main = dispatch_get_main_ ...

  8. C#关系运算符

    一.C#关系运算符 C#语言的关系运算符是对操作数的比较运算. 二.示例 using System;using System.Collections.Generic;using System.Linq ...

  9. zabbix mysql 迁移 增加分区

    1.zabbix mysql 目录清单 --basedir=/usr/local/web/mysql --datadir=/data/mysql --log-error=/data/mysql/sys ...

  10. 本地已经存在的项目如何跟github发生关联

    切换到本地项目地址 git init 初始化项目.该步骤会创建一个 .git文件夹是附属于该仓库的工作树. git add . git commit -am 'initial commit' git ...