场景: 由于在一个方法中存在多个不同业务操作
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 级别的,这样每次查询结束都会清掉一级缓存