对于mybatis的缓存,我们往往有这样两个疑问:一级缓存、二级缓存的过期时间是多少?后台是否有个线程在检测?针对这两个问题,见下面的分析:

1、一级缓存无过期时间,只有生命周期

(1)MyBatis在开启一个数据库会话时,会创建一个新的SqlSession对象,SqlSession对象中会有一个Executor对象,Executor对象中持有一个PerpetualCache对象,见下面代码。当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。

protected BaseExecutor(Configuration configuration, Transaction transaction) {
this.transaction = transaction;
this.deferredLoads = new ConcurrentLinkedQueue<DeferredLoad>();
this.localCache = new PerpetualCache("LocalCache");
this.localOutputParameterCache = new PerpetualCache("LocalOutputParameterCache");
this.closed = false;
this.configuration = configuration;
this.wrapper = this;
}

(2)如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用;

(3)如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用;

(4)SqlSession中执行了任何一个更新操作,例如:update、delete、insert ,都会清空PerpetualCache对象的数据,但是该对象可以继续使用;

2、二级缓存有过期时间,但没有后台线程进行检测

需要注意的是,并不是key-value的过期时间,而是这个cache的过期时间,是flushInterval,意味着整个清空缓存cache,所以不需要后台线程去定时检测。

每当存取数据的时候,都有检测一下cache的生命时间,默认是1小时,如果这个cache存活了一个小时,那么将整个清空一下。

public class ScheduledCache implements Cache
{

    private final Cache delegate;
    protected long clearInterval;
    protected long lastClear;

    public ScheduledCache(Cache delegate)
    {
        this.delegate = delegate;
        this.clearInterval = 60 * 60 * 1000;
        this.lastClear = System.currentTimeMillis();
    }

    public void setClearInterval(long clearInterval)
    {
        this.clearInterval = clearInterval;
    }

    @Override
    public String getId()
    {
        return delegate.getId();
    }

    @Override
    public int getSize()
    {
        clearWhenStale();
        return delegate.getSize();
    }

    @Override
    public void putObject(Object key, Object object)
    {
        clearWhenStale();
        delegate.putObject(key, object);
    }

    @Override
    public Object getObject(Object key)
    {
        return clearWhenStale() ? null : delegate.getObject(key);
    }

    @Override
    public Object removeObject(Object key)
    {
        clearWhenStale();
        return delegate.removeObject(key);
    }

    @Override
    public void clear()
    {
        lastClear = System.currentTimeMillis();
        delegate.clear();
    }

    @Override
    public ReadWriteLock getReadWriteLock()
    {
        return null;
    }

    @Override
    public int hashCode()
    {
        return delegate.hashCode();
    }

    @Override
    public boolean equals(Object obj)
    {
        return delegate.equals(obj);
    }

    private boolean clearWhenStale()
    {
        if (System.currentTimeMillis() - lastClear > clearInterval)
        {
            clear();
            return true;
        }
        return false;
    }

}

标签: none

添加新评论