漫步云端

移动开发(Android、iPhone、Windows Mobile) | JAVA | C | C++ | .net | Objective C | 微软企业开发技术 | 嵌入式系统设计与开发
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Ibatis缓存应用的一个小问题(转)

Posted on 2010-11-08 11:50  charley_yang  阅读(1708)  评论(0编辑  收藏  举报

最近在做执法系统重构功能的开发,发现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 id="CaseSummaryCache" implementation="MEMORY">
      <flushInterval hours="24"/>
      <flushOnExecute statement="CaseSummary.AddCaseSummary"/>
      <flushOnExecute statement="CaseSummary.UpdateCaseSummary"/>
      <flushOnExecute statement="CaseSummary.DeleteCaseSummary"/>
      <flushOnExecute statement="CaseSummary.DeleteCaseSummarys"/>
      <flushOnExecute statement="CaseSummary.UpdateCaseSummaryName"/>
      <property name="Type" value="WEAK"/>
    </cacheModel>
  </cacheModels>
  <!--字段映射-->
  <resultMaps>
    <resultMap id="CaseSummaryResult" class="CaseSummary">
      <result property="Id" column="ID" />
      <result property="Code" column="CODE" />
      <result property="File" column="FILE" />
      <result property="Name" column="NAME" />
      <result property="Administration" column="ADMINISTRATION" />
      <result property="Category" column="CATEGORY" />
      <result property="Subject" column="SUBJECT" />
      <result property="Items" column="ITEMS" />
      <result property="Time" column="TIME" />
      <result property="Address" column="ADDRESS" />
      <result property="Income" column="INCOME" />
      <result property="Created" column="CREATED" />
      <result property="Creater" column="CREATER" />
      <result property="Organization" column="ORGANIZATION" />
      <result property="Amerce" column="AMERCE" />
      <result property="Status" column="STATUS" />
      <result property="Description" column="DESCRIPTION" />
      <result property="Road" column="ROAD" />
      <result property="PileStart" column="PILE_START" />
      <result property="PileEnd" column="PILE_END" />
<result property="Propertys" column="ID" select="CaseProperty.GetPropertysBySummaryID" />
      <result property="PunishType" column="PUNISH_TYPE" />
    </resultMap>
  </resultMaps>
  <statements>
    <!--获取多条-->
<select id="GetCaseSummarys" resultMap="CaseSummaryResult" parameterClass="CaseSummary" cacheModel="CaseSummaryCache">
      select "ID", CODE, "FILE", "NAME", ADMINISTRATION, "CATEGORY", SUBJECT, ITEMS, "TIME", ADDRESS, INCOME, CREATED, CREATER, "ORGANIZATION",AMERCE, STATUS, DESCRIPTION, ROAD, PILE_START, PILE_END, PUNISH_TYPE
      from T_CASE_SUMMARY
      where 1=1
      <include refid="WhrClauseEqual" />
    </select>
  </statements>
</sqlMap>
关联表(CaseProperty)
<?xml version="1.0" encoding="utf-8" ?>
<sqlMap namespace="CaseProperty" xmlns="http://ibatis.apache.org/mapping" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <!--别名-->
  <alias>
    <typeAlias alias="CaseProperty" type="Comit.TE.Web.Domain.Cases.CaseProperty, Comit.TE.Web.Domain" />
  </alias>
  <!--缓存模型-->
  <cacheModels>
    <cacheModel id="CasePropertyCache" implementation="MEMORY">
      <flushInterval hours="24"/>
      <flushOnExecute statement="CaseProperty.AddCaseProperty"/>
      <flushOnExecute statement="CaseProperty.UpdateCaseProperty"/>
      <flushOnExecute statement="CaseProperty.DeleteCaseProperty"/>
      <flushOnExecute statement="CaseProperty.DeleteCasePropertys"/>
      <flushOnExecute statement="CaseProperty.DeleteCasePropertyBySummary"/>
      <property name="Type" value="WEAK"/>
    </cacheModel>
  </cacheModels>
  <!--字段映射-->
  <resultMaps>
    <resultMap id="CasePropertyResult" class="CaseProperty">
      <result property="Id" column="ID" />
      <result property="Summary" column="SUMMARY" />
      <result property="Name" column="NAME" />
      <result property="Value" column="VALUE" />
      <result property="Shift" column="SHIFT" />
    </resultMap>
  </resultMaps>
  <statements>
    <!--根据主表ID获取信息-->
<select id="GetPropertysBySummaryID" resultMap="CasePropertyResult" parameterClass="int" cacheModel="CasePropertyCache">
      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给忽悠了。