`
lifei114
  • 浏览: 26613 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

IBatis 的缓存机制之 Select Query缓存

阅读更多

IBatis 的缓存机制之 Select Query缓存

 

可以按下面的代码在你的 SqlMap.xml 里配置,如下:

 

<cacheModel id="users-cache" imlementation="LRU" readOnly="true" serialize="true">
<flushInterval hours="24"/>
<flushOnExecute statement="users.update"/>
<property name="size" value="1000" />
</cacheModel>

<statement id="findUsers" parameterClass="int" cacheModel="users-cache">
select * from users where member_id = #value#
</statement>

 

我们来跟踪一下代码,看 IBatis 是如何实现缓存的,

还是由类:SqlMapParser 来解析这个配置的,代码如下:

 private void addCacheModelNodelets() {
    parser.addNodelet("/sqlMap/cacheModel", new Nodelet() {
      public void process(Node node) throws Exception {
        Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
        String id = state.applyNamespace(attributes.getProperty("id"));
        String type = attributes.getProperty("type");
        String readOnlyAttr = attributes.getProperty("readOnly");
        Boolean readOnly = readOnlyAttr == null || readOnlyAttr.length() <= 0 ? null : new Boolean("true".equals(readOnlyAttr));
        String serializeAttr = attributes.getProperty("serialize");
        Boolean serialize = serializeAttr == null || serializeAttr.length() <= 0 ? null : new Boolean("true".equals(serializeAttr));
        type = state.getConfig().getTypeHandlerFactory().resolveAlias(type);
        Class clazz = Resources.classForName(type);
        if (readOnly == null) {
          readOnly = Boolean.TRUE;
        }
        if (serialize == null) {
          serialize = Boolean.FALSE;
        }
        CacheModelConfig cacheConfig = state.getConfig().newCacheModelConfig(id, (CacheController) Resources.instantiate(clazz), readOnly.booleanValue(), serialize.booleanValue());
        state.setCacheConfig(cacheConfig);
      }
    });
    parser.addNodelet("/sqlMap/cacheModel/end()", new Nodelet() {
      public void process(Node node) throws Exception {
        state.getCacheConfig().setControllerProperties(state.getCacheProps());
      }
    });
    parser.addNodelet("/sqlMap/cacheModel/property", new Nodelet() {
      public void process(Node node) throws Exception {
        state.getConfig().getErrorContext().setMoreInfo("Check the cache model properties.");
        Properties attributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
        String name = attributes.getProperty("name");
        String value = NodeletUtils.parsePropertyTokens(attributes.getProperty("value"), state.getGlobalProps());
        state.getCacheProps().setProperty(name, value);
      }
    });
    parser.addNodelet("/sqlMap/cacheModel/flushOnExecute", new Nodelet() {
      public void process(Node node) throws Exception {
        Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
        String statement = childAttributes.getProperty("statement");
        state.getCacheConfig().addFlushTriggerStatement(statement);
      }
    });
    parser.addNodelet("/sqlMap/cacheModel/flushInterval", new Nodelet() {
      public void process(Node node) throws Exception {
        Properties childAttributes = NodeletUtils.parseAttributes(node, state.getGlobalProps());
        try {
          int milliseconds = childAttributes.getProperty("milliseconds") == null ? 0 : Integer.parseInt(childAttributes.getProperty("milliseconds"));
          int seconds = childAttributes.getProperty("seconds") == null ? 0 : Integer.parseInt(childAttributes.getProperty("seconds"));
          int minutes = childAttributes.getProperty("minutes") == null ? 0 : Integer.parseInt(childAttributes.getProperty("minutes"));
          int hours = childAttributes.getProperty("hours") == null ? 0 : Integer.parseInt(childAttributes.getProperty("hours"));
          state.getCacheConfig().setFlushInterval(hours, minutes, seconds, milliseconds);
        } catch (NumberFormatException e) {
          throw new RuntimeException("Error building cache in '" + "resourceNAME" + "'.  Flush interval milliseconds must be a valid long integer value.  Cause: " + e, e);
        }
      }
    });
  }

 带缓存的SQL具体的执行是由类:CachingStatement  来执行,如要执行executeQueryForList动作,其执行的代码如下:

  public List executeQueryForList(StatementScope statementScope, Transaction trans, Object parameterObject, int skipResults, int maxResults)
      throws SQLException {
    CacheKey cacheKey = getCacheKey(statementScope, parameterObject);
    cacheKey.update("executeQueryForList");
    cacheKey.update(skipResults);
    cacheKey.update(maxResults);
    Object listAsObject = cacheModel.getObject(cacheKey);
    List list;
    if(listAsObject == CacheModel.NULL_OBJECT){
      // The cached object was null
      list = null;
    }else if (listAsObject == null) {
      list = statement.executeQueryForList(statementScope, trans, parameterObject, skipResults, maxResults);
      cacheModel.putObject(cacheKey, list);
    }else{
      list = (List) listAsObject;
    }
    return list;
  }

 

 上面的代码很明显,如果在缓存中存在此数据就直接返回此数据,如果没有找到则执行具体的查询操作,并将查询后的结果缓存到缓存中去,再次使用时就直接返回缓存里的数据了。

这里面的 CacheKey 很有意思,Ibatis 是按照 SQL 加参数并加参数个数进行 Hash 组成一个 Key。因此我们的查询中 SQL的参数变化的频率太多时,使用缓存的效果将十分不明显,

甚至可能取得相反的效果,每次查询缓存也是需要时间的。至于 IBatis 何时更新缓存里的数据,请参看我之前写的这遍文章 IBatis 的缓存机制( http://lifei114.iteye.com/admin/blogs/581795

具体项目中如何使用缓存我认为具体问题具体分析,不要盲目相信科学神话,“大家都在用的东西不一定就适合自己用”,以上供大家参考,欢迎大家一起讨论,我的 QQ: 535043378 ,最近加的人太多请注明 "JavaEye"。

r

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    Mybatis核心应用配置与原理解析1

    缓存机制可以分为一级缓存和二级缓存两种。下面我们将对 Mybatis 的缓存机制进行详细的分析和解释。 一级缓存 一级缓存是 Mybatis 中的一种缓存机制,用于缓存同一个会话中的查询结果。它可以减少对数据库的查询...

    持久层框架Ibatis

    4. **缓存机制**:内置了本地缓存和二级缓存,提高了数据读取速度,减少了对数据库的访问。 5. **动态SQL**:Ibatis 提供了动态SQL的功能,使得在XML映射文件中可以写入条件判断、循环等复杂的SQL逻辑。 **二、...

    SQL&Ibatis学习 ppt

    5. 强大的功能:了解Ibatis的缓存机制、结果集映射(包括一对一、一对多、多对多)、延迟加载等功能,以及如何进行参数和结果的自定义类型处理器。 6. 集成与配置:学习如何将Ibatis框架集成到Spring等其他框架中,...

    iBatis入门

    &lt;property name="Pool.PingQuery" value="select 1 from sample"/&gt; ``` 在上述配置文件中,我们定义了以下几个关键部分: - **settings**:用于配置iBatis的行为,如缓存启用、延迟加载等。 - **...

    20190610_MyBatis核心配置回顾和拓展_田超凡.docx

    - 提供缓存级别和缓存机制。 #### MyBatis核心配置 - **核心配置文件**:通常命名为`mybatis-config.xml`,包含了全局配置信息。 - **主要配置项**: - **environments**:环境配置,包含事务管理和数据源配置。...

    IBtisNet演示

    IBatisNet是基于.NET的开源项目,它源于Java版的iBATIS,但针对.NET环境进行了优化。它的主要功能包括动态SQL生成、自动事务处理以及对各种数据库的兼容性。通过使用XML配置文件,开发者可以定义SQL语句和对象之间的...

    J2ME数据库操作模糊查询

    String query = "SELECT * FROM Contacts WHERE Name LIKE ? "; PreparedStatement pstmt = connection.prepareStatement(query); pstmt.setString(1, "%" + userInput + "%"); ResultSet rs = pstmt.executeQuery()...

    hibernat培训.ppt

    此外,还讨论了SQL/JDBC、Entity Bean CMP、JDO、Apache OJB和iBATIS等不同持久化方案的优缺点,其中Hibernate因其成熟、流行和强大的功能而被广泛采用。 **二、Hibernate入门** Hibernate是一个优秀的开源ORM框架...

    自整理Java关于基础和框架的面试题

    - **OSCache**:一种缓存机制,用于提高Web应用的性能。 ##### 经常访问的技术网站 - Stack Overflow、GitHub、MDN Web Docs等。 ##### 项目团队中交流的工具 - Slack、钉钉、企业微信等。 ##### 平时浏览的书籍 ...

    java必备知识点大全.pdf

    Hibernate、Ibatis、Jdbc三者的区别:Hibernate和Ibatis都是JDBC的封装框架,但Hibernate是全自动的ORM映射,而Ibatis是半自动的。 Hibernate的运行原理:Hibernate通过映射关系将Java对象和数据库表进行映射。 ...

    Hibernate笔记

    - **Query:** 负责执行HQL(Hibernate Query Language)查询语句。 - **Transaction:** 负责事务控制,Hibernate必须使用代码控制事务。 #### 四、Hibernate主键生成方式 1. **内置主键生成策略:** - **...

    hibernat培训教程,基础教程

    JDBC API虽然成熟,但其面向语句的特性和在Insert、Update、Select操作时需要指定结构化关系的特性,增加了设计和实现的复杂性。 **基于关系数据库的持久层可选方案** - SQL/JDBC:成熟且广泛使用,但通过DAO模式...

    spring chm文档

    8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量 8.3.5. 示例 8.3.6. 运行集成测试 8.4. 更多资源 II. 中间层数据访问 9. 事务管理 9.1. 简介 9.2. 动机 9.3....

    Spring 2.0 开发参考手册

    8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量 8.3.5. 示例 8.3.6. 运行集成测试 8.4. 更多资源 II. 中间层数据访问 9. 事务管理 9.1. 简介 9.2. 动机 9.3....

    Spring-Reference_zh_CN(Spring中文参考手册)

    8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量 8.3.5. 示例 8.3.6. 运行集成测试 8.4. 更多资源 II. 中间层数据访问 9. 事务管理 9.1. 简介 9.2. 动机 9.3. 关键抽象 ...

Global site tag (gtag.js) - Google Analytics