最近在做执法系统重构功能的开发,发现Ibatis的缓存一个应用的问题,跟大家分享一下。
使用过Ibatis缓存的同事可能也会遇到过这个问题。
背景:
    接过项目经理的一个案件转办的任务,功能大概是这样的,一个表单的新增、修改(新增、修改都只需要修改关联表的数据,主表数据是不需要用的)等,然后就提交审核,功能完成,提交给测试组。很简单吧。
    第二天,MT跟我说:“怎么你的转办功能这样子的呀???都保存不了数据。”然后我又回来测了下,没发现问题,郁闷中……。再回来找找问题,后来发现原来是在不同的环境下体现出来的效果不同,在开发环境下是可以正常读到数据,但在IIS下就读不到数据。在网上找一下,没找到解决方法,怎么办,又郁闷中……。后来跑去问土华,土华给了我一个很有很好的提示:是Ibatis缓存的问题,具体问题出在哪里,再找找咯。然后我就跟着这个思路去找,找找找……。终于找到了,爽呀!真的是Ibatis缓存问题。
数据表设计:
看代码,了解下数据表的结构和数据读取
主表(CaseSummary)
<?xml version="1.0" encoding="utf-8" ?>
<sqlMap namespace="CaseSummary" xmlns="http://ibatis.apache.org/mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <!--别名-->
  <alias>
    <typeAlias alias="CaseSummary" type="Comit.TE.Web.Domain.Cases.CaseSummary, Comit.TE.Web.Domain" />
  </alias>
  <!--缓存模型-->
  <cacheModels>
    <cacheModel >
      select ID, SUMMARY, NAME, VALUE, SHIFT
      from T_CASE_PROPERTY
      where SUMMARY=$SUMMARY$
    </select>
  </statements>
</sqlMap>

 

public ActionResult Edits(string code)  
        {

            try
            {//读取(在IIS下读取数据是有问题的,只能读取到上一次的缓存数据,取不到最新的数据)
                caseSummary = CaseSummaryService.GetCaseSummarys(HttpContext, new CaseSummary() { Code = code }).FirstOrDefault();  

        }
            catch (Exception e)
            {
                HandleException(Response, e);
            }
            return Json(caseSummary, JsonRequestBehavior.AllowGet);
        }

public ActionResult Edits([ModelBinder(typeof(JsonBinder<CaseProperty>))]List<CaseProperty> propertys)
        {
            try
            {

                CasePropertyService.UpdateCaseProperty(HttpContext, propertys); //对表单修改,只修改关联表(已经对property的数据进行更新了,但还是取不到数据)

            }
            catch (Exception e)
            {
                HandleException(Response, e);
            }
            return Json(true);
        }

问题就出在“只修改关联表”,这样一来Ibatis把propertys的物理数据表和Ibatis缓存同时更新。在代码执行“GetCaseSummarys“时,读到propertys的是缓存数据是并不是最新的。实际上,此时propertys的缓存数据是有两个版本,要拿到最新的数据有两种方法:
1.修改读取的方法,直接调用“Getpropertys”读取property表的数据;
2.修改更新的方法,先调用“UpdateCaseSummary”把主表的缓存版本更新,再执行“GetCaseSummarys”;
      小结,一个小实验来证明得来,Ibatis的缓存在VS的调试环境下没起到缓存的做用,在IIS下程序就能真正起到数据缓存的作用,并且同一个数据对象可能会存在多个版本的缓存数据。如果有哪位同事用到Ibatis缓存机制来优化系统的性能,那就要留意缓存的问题。在VS调用下看到的效果并不是真实的效果。小提醒:你看到的并不一定是你所想的,小心被VS给忽悠了。

相关文章: