mybatis的缓存机制

来源:互联网 发布:手机设置添加网络ssid 编辑:程序博客网 时间:2024/05/21 06:35

1. 什么是一级缓存? 为什么使用一级缓存?

每当我们使用mybatis开启一次和数据库的会话的时候,mybatis会创建一个sqlsession对象表示一次数据库回话。
在对数据库的一次会话中,我们很有可能在极短的时间内做出相同的查询语句,如果不采取一些措施的话, 在一定程度上会影响程序运行的效率的。

为了解决这一问题,mybatis会在表示会话的sqlsession对象中建立一个简单的缓存(cache),将每次查询的结果缓存起来,当下次查询的时候,如果判断和先前有完全一样的查询,会直接从缓存中将结果取出,返回给用户,这样就不会再进行一次不必要的数据库查询了。

如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。

脏读:
脏读就是指读到还没完全弄好的数据。比如,你要读取数据库中的字段A、字段B,你读取时恰巧有其他用户正在更新这2个字段,而且是先更新A、再更新B,此时就可能会发生脏读:
1、如果都未更新你就读取了,或者都更新完了你才读取,这都不是脏读,因为你得到的是更新前的有效值,或完全更新后的值。
2、如果那个用户更新一半你就读取了,也就是说更新了A,正打算要更新B但尚未更新时,你就读取了,此时你得到的就是脏数据。
避免脏读的办法就是采取事务,使得他用户正在更新时锁定数据库,阻止你读取,直至全部完成才让你读取。
一级缓存基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有缓存(cache)就将清空。PerpetualCache实现原理其实很简单,其内部就是通过一个简单的HashMap<k,v>来实现的,没有其他的任何限制。

2.一级缓存的生命周期有多长?
a.MyBatis在开启一个数据库会话时,会创建一个新的SqlSession对象,SqlSession对象中会有一个新的Executor对象,Executor对象中持有一个新的PerpetualCache对象;当会话结束时,SqlSession对象及其内部的Executor对象还有PerpetualCache对象也一并释放掉。
b.如果SqlSession调用了close()方法,会释放掉一级缓存PerpetualCache对象,一级缓存将不可用;
c.如果SqlSession调用了clearCache(),会清空PerpetualCache对象中的数据,但是该对象仍可使用;
d.SqlSession中执行了任何一个update操作(update()、delete()、insert()),都会清空PerpetualCache对象的数据,但是该对象可以继续使用;


3.Cache中Map的key值:CacheKey

我们知道,Cache最核心的实现其实就是一个Map,将本次查询使用的特征值作为key,将查询结果作为value存储到Map中。

现在最核心的问题出现了:怎样来确定一次查询的特征值?
换句话说就是:怎样判断某两次查询是完全相同的查询?
也可以这样说:如何确定Cache中的key值?

MyBatis认为,对于两次查询,如果以下条件都完全一样,那么就认为它们是完全相同的两次查询:
1. 传入的statementId
   传入的statementId,对于MyBatis而言,你要使用它,必须需要一个statementId,它代表着你将执行什么样的Sql;
2. 查询时要求的结果集中的结果范围(结果的范围通过rowBounds.offset和rowBounds.limit表示);
3. 这次查询所产生的最终要传递给JDBC java.sql.Preparedstatement的Sql语句字符串(boundSql.getSql())
4. 传递给java.sql.Statement要设置的参数值
综上所述,CacheKey由以下条件决定:statementId  + rowBounds  + 传递给JDBC的SQL  + 传递给JDBC的参数值

原文: http://www.xuebuyuan.com/2231229.html





原创粉丝点击