鉴于网络上对于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) |