Ibatis 缓存

字体大小: 中小 标准 ->行高大小: 标准

相关类

 

ibatis配置文件

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN" 
    "http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap namespace="User">
    <cacheModel id="user_cache" type="MEMORY">
        <flushInterval hours="24"/>
        <flushOnExecute statement="getUser"/>
        <property name="reference-type" value="WEAK" />
    </cacheModel>
    <typeAlias alias="user" type="com.model.User"/>
    <select id="getUser" parameterClass="java.lang.String" resultClass="user" 
        cacheModel="user_cache"> <![CDATA[
        select name as name,id
        from user
        where name = #name#]]> </select>
</sqlMap>

当配置文件配置了使用缓存后,实现执行时会使用CachingStatement来执行sql,相关代码

  public Object executeQueryForObject(StatementScope statementScope, Transaction trans, Object parameterObject, Object resultObject)
      throws SQLException {
    CacheKey cacheKey = getCacheKey(statementScope, parameterObject);
    cacheKey.update("executeQueryForObject");
    Object object = cacheModel.getObject(cacheKey);//获取缓存
    if (object == CacheModel.NULL_OBJECT){
        //    This was cached, but null
        object = null;
    }else if (object == null) {
       object = statement.executeQueryForObject(statementScope, trans, parameterObject, resultObject);
       cacheModel.putObject(cacheKey, object);
    }
    return object;
  }

key的生成方法

sql的id、参数、sql语句,还有一些固定参数生成hashcode,放入cacheKey

所以同一sql第二次执行时,缓存如果还有,则直接返回结果,不再执行sql

  public CacheKey getCacheKey(StatementScope statementScope, Object parameterObject) {
    Sql sql = statementScope.getSql();
    ParameterMap pmap = sql.getParameterMap(statementScope, parameterObject);
    CacheKey cacheKey = pmap.getCacheKey(statementScope, parameterObject);
    cacheKey.update(id);//sql的id
    cacheKey.update(baseCacheKey);

//select name as name,id from user where name = ? cacheKey.update(sql.getSql(statementScope, parameterObject));
//Fixes bug 953001 return cacheKey; }

User user = (User) sqlMapClient.queryForObject("getUser", "test");
User user2 = (User) sqlMapClient.queryForObject("getUser", "test");

执行结果:

第一次执行

hashcode=-1700962362
CacheModel - Cache 'User.user_cache': cache miss
SimpleDataSource - Created connection 21185076.
Connection - {conn-100000} Connection
Connection - {conn-100000} Preparing Statement: select name as name,id from user where name = ?
PreparedStatement - {pstm-100001} Executing Statement: select name as name,id from user where name = ?
PreparedStatement - {pstm-100001} Parameters: [test]
PreparedStatement - {pstm-100001} Types: [java.lang.String]
ResultSet - {rset-100002} ResultSet
ResultSet - {rset-100002} Header: [name, id]
ResultSet - {rset-100002} Result: [test, 1]
CacheModel - Cache 'User.user_cache': flushed
CacheModel - Cache 'User.user_cache': stored object 'com.model.User@15212bc'
SimpleDataSource - Returned connection 21185076 to pool.

每二次执行
CacheModel - Cache 'User.user_cache': retrieved object 'com.model.User@15212bc'
hashcode=-1700962362

 

问题:当数据库数据已更新时,是否还是直接返回缓存,是否要在缓存过期后才会重新查询?

 

        User user = (User) sqlMapClient.queryForObject("getUser", "test");
        System.out.println("id=" + user.getId());
        
        Thread.sleep(20000);
        
        User user2 = (User) sqlMapClient.queryForObject("getUser", "test");
        System.out.println("id=" + user.getId());

 

用以上代码测试,执行第一条后,立即手工执行update,改变数据 库数据,第二次的结果仍是缓存结果

所以缓存会等到过期后才更新,不会自动去更新

此文章由 http://www.ositren.com 收集整理 ,地址为: http://www.ositren.com/htmls/68649.html