Chinaunix首页 | 论坛 | 博客
  • 博客访问: 534840
  • 博文数量: 260
  • 博客积分: 10435
  • 博客等级: 上将
  • 技术积分: 1939
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-24 14:50
文章分类

全部博文(260)

文章存档

2011年(22)

2010年(209)

2009年(29)

我的朋友

分类: Java

2010-07-08 16:11:47

鉴于网络上对于ibatis的缓存介绍不够详细,特别是对于session的概念没有明确指出,都是人云亦云sqlMapClient相当于一个session,本人阅读了ibatis源代码,得出如下结论:

 

Ibatis一个sqlMapClient实例对应一个SqlMapExecutorDelegate实例,如果sqlMap被多线程执行,那么会共享这两个实例,ibatis对于每个线程都会创建一个SqlMapSessionImpl实例来表示session这个概念,每个线程的数据库操作方法都在本session内执行,SqlMapExecutorDelegate保存了一个ThreadLocal来保存最大同时能够运行的session数目,也就是配置文件中的maxSessions="800"。一个SqlMapSessionImpl对应ThreadLocal中的一个session.当执行查询操作时,如果有缓存,ibatis会首先根据参数、statement的id、缓存的id等hash一个CacheKey出来,如果该缓存是是可读写缓存,那么将本session也hash进去,然后以这个对象为key查找缓存,由于有了session的特征,这样对于每一个session中查询出的数据的修改都不会影响另一个session的数据。如果该缓存是只读缓存,则不将session的特征hash进去,意思就是说,该sqlmap实例中的所有session都可以共享这一个查询出来的数据,对数据的修改也会造成对另一个session读出数据的影响。

 所以,按照这个道理,cache的配置中如果readonly为true,则该sqlMap的所有session共享该实例,如果修改其中一个实例,那么会对其他session造成影响。如果readonly为false,由于该实例只是对该session有效,所以,修改也只会对本session有效。Serialize参数为true并且readonly为false时,将会对缓存数据进行序列化保存,读取时再反序列化。如果多个session访问,则Serialize会返回不反序列化之后的对象(相当于复制的对象,也可以这样理解,处理这一点和readonly为true时不一样,其他处理方式都一样);当readonly为true时,不论是否设置了Serialize,都会忽略该参数的设置,处理的结果和值设置readonly效果一样。

下面是两个关于该属性设置的关键代码,一读就明白了。(红色部分)

cacheModel.java 关键部分

/**

   * Get an object out of the cache.

   * A side effect of this method is that is may clear the cache if it has not been

   * cleared in the flushInterval.

   *

   * @param key The key of the object to be returned

   * @return The cached object (or null)

   */

  public Object getObject(CacheKey key) {

    synchronized (this) {

      if (flushInterval != NO_FLUSH_INTERVAL

          && System.currentTimeMillis() - lastFlush > flushInterval) {

        flush();

      }

    }

 

    Object value = null;

    synchronized (getLock(key)) {

      value = controller.getObject(this, key);

    }

 

    if (serialize && !readOnly && (value != NULL_OBJECT && value != null)) {

      try {

        ByteArrayInputStream bis = new ByteArrayInputStream((byte[]) value);

        ObjectInputStream ois = new ObjectInputStream(bis);

        value = ois.readObject();

        ois.close();

      } catch (Exception e) {

        throw new NestedRuntimeException("Error caching serializable object.  Be sure you're not attempting to use " +

            "a serialized cache for an object that may be taking advantage of lazy loading.  Cause: " + e, e);

      }

    }

 

    synchronized (STATS_LOCK) {

      requests++;

      if (value != null) {

        hits++;

      }

    }

 

    return value == NULL_OBJECT ? null : value;

 

  }

 

  /**

   * Add an object to the cache

   *

   * @param key   The key of the object to be cached

   * @param value The object to be cached

   */

  public void putObject(CacheKey key, Object value) {

    if (null == value) value = NULL_OBJECT;

    if (serialize && !readOnly && value != NULL_OBJECT) {

      try {

        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        ObjectOutputStream oos = new ObjectOutputStream(bos);

        oos.writeObject(value);

        oos.flush();

        oos.close();

        value = bos.toByteArray();

      } catch (IOException e) {

        throw new NestedRuntimeException("Error caching serializable object.  Cause: " + e, e);

      }

    }

    synchronized (getLock(key)) {

      controller.putObject(this, key, value);

    }

  }

 

CachingStatement.java 关键部分

  public CacheKey getCacheKey(RequestScope request, Object parameterObject) {

    CacheKey key = statement.getCacheKey(request, parameterObject);

    if (!cacheModel.isReadOnly() && !cacheModel.isSerialize()) {

      key.update(request.getSession());

    }

    return key;

  }

 



本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/lovingprince/archive/2007/11/13/1882633.aspx
阅读(1189) | 评论(0) | 转发(0) |
0

上一篇:linuc 心跳 主从

下一篇:web rest

给主人留下些什么吧!~~