参考:http://blog.csdn.net/luanlouis/article/details/41280959
Mybatis是一个小巧、强大的ORM框架,主要功能与Hibernate类似,但比Hibernate更加灵活,简单。
我们都知道,数据库操作是一个应用中比较耗费资源的一点,Mybatis作为最好用的orm框架,当然在这方面也做了优化,同样,与hibernate类似,mybatis也提供了一级缓存和二级缓存来提高数据访问层(Dao)的性能。
下面详细介绍一个mybatis的一级缓存。
- 一级缓存简述及引入一级缓存的原因。
在某些情况下,我们需要在一次连接上进行多次相同的查询(虽然现在没想起来这样的场景,但它确实存在),这就意味着需要进行多次数据库操作,但是,重点在于多次查询的结果是相同的,这样的多次查询既没有意义有占用资源(数据库查询是非常耗费系统资源的),mybatis为了解决这个问题,就引入了以及缓存。
每次查询时,mybatis会在SqlSession中创建一块缓存区,将查询接环缓存到这里,若在此次连接中有相同的查询,则直接从一级缓存总获取查询结果,不需要查询数据库,从而提高了系统性能和响应速度。
- mybatis中一级缓存的组织形式
mybatis的一级缓存是SqlSession对象内的一块内存区域,由于SqlSession代表了一次数据库连接,下面来看一下一级缓存与SqlSession的关系
实际上,SqlSession只是mybatis对外提供的一个统一接口,对应执行sql语句的活儿都是交给Executor来处理的,这样一来,Executor顺理成章的维护一级Cache,图中的BaseExecutor是Executor的实现类,PerpetualCache是Cache接口的一个实现类。下面来看一下源代码就一目了然了。
public class DefaultSqlSession implements SqlSession {
private Configuration configuration;
//引入Executor
private Executor executor;
......
}
public abstract class BaseExecutor implements Executor {
private static final Log log = LogFactory.getLog(BaseExecutor.class);
// for backward compatibility with 3.0 style logging
private static final Log connectionLog = LogFactory.getLog(Connection.class);
protected Transaction transaction;
protected ConcurrentLinkedQueue<DeferredLoad> deferredLoads;
//引入一级缓存
protected PerpetualCache localCache;
protected PerpetualCache localOutputParameterCache;
protected Configuration configuration;
protected int queryStack = 0;
protected List<BatchResult> batchResults = new ArrayList<BatchResult>();
private boolean closed;
}
小结,SqlSession包含Executor,Executor包含Cache。
- 一级缓存的生命周期
当SqlSession被创建时,一级缓存生命周期开始,当SqlSession被释放时,一级缓存生命周期结束。
具体规则如下:
a)调用SqlSession的close()方法,一级缓存被释放掉,一级缓存不可用。
b)调用SqlSession的clearCache()方法,清空一级缓存,但一级缓存仍可用。
c)执行DML的sql语句,会 清空缓存,但一级缓存可用。
- 一级缓存的工作流程
1)对于一个查询,根据statementId,params和rowBounds构建一个key
2)根据这个key从cache(map)中获取数据。
3)若结果不为空,则命中缓存,不再需要查询数据库。
4)没有命中
4.1)查询数据库,得到查询结果。
4.2)将key和得到的查询结果(value)放入缓存中。
4.3)返回结果。
- 一级缓存的性能分析。
a)mybatis的一级缓存是由map实现,相对简单,并且没有对容量的限制,那么这样会不会有由于map过大导致jvm内存溢出呢?mybatis这样设计当然有他的道理。
a.1)一般来说,SqlSession对象不会存在太久,当执行完sql操作后就被释放掉了。
a.2)只要执行DML操作,都会情况缓存。
a.3)还可以手动清楚缓存中的内存(SqlSession的clearCache()方法)
b)mybatis的一级缓存是一个粗粒度的缓存,没有更新缓存和缓存过期等概念,所以在使用是,应该注意一下几点:
b.1)对于更新频率较大、且对数据准确性要求较高的,应尽量控制好SqlSession中一级缓存数据的存放时间,以免造成数据的误差。
b.2)对于频繁执行的大范围的select,尽量控制其结果在一级缓存中的存放时间,避免占用太多内存资源。
版权声明:本文为博主原创文章,未经博主允许不得转载。