概念:
mybatis缓存也称为查询缓存
一级缓存:
一级缓存是SqlSession级别的缓存;当一个sqlsession查询到一个对象后会把该对象保存到缓存中,当在同一sqlsession中再次执行同样的sql语句时会直接从一级缓存中获取数据
二级缓存:
二级缓存是mapper级别的缓存;多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession去操作数据库得到数据会存在二级缓存区域,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的
测试缓存
public class TestUserDao {
private UserDao userDao = new UserDao();
/**测试一级缓存*/
// @Test
public void test() {
userDao.selectOne(1);
}
/**测试二级缓存*/
@Test
public void test2(){
userDao.selectOne(3);
userDao.selectOne(3);
/*不同的sqlSession*/
}
}
public class UserDao {
SqlSession session = null;
/**测试一级缓存*/
public User selectOne(Integer id){
User user =null;
try {
session=MybatisSessionFactory.getSession();
user = session.selectOne("com.xxjqr.cache.userMapper.selectUser",id);
user = session.selectOne("com.xxjqr.cache.userMapper.selectUser",id);
session.commit();
/*此时用的是一个sqlSession*/
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
MybatisSessionFactory.closeSession();
} catch (Exception e) {
e.printStackTrace();
}
}
return user;
}
/**测试二级缓存*/
public User selectOne2(Integer id){
User user =null;
try {
session=MybatisSessionFactory.getSession();
user = session.selectOne("com.xxjqr.cache.userMapper.selectUser",id);
} catch (Exception e) {
e.printStackTrace();
}finally{
try {
MybatisSessionFactory.closeSession();
} catch (Exception e) {
e.printStackTrace();
}
}
return user;
}
}
经测试可知一级缓存默认是开启的;二级缓存没用
开启二级缓存
- 打开二级缓存总开关 打开总开关,只需要在mybatis总配置文件中加入一行设置
<settings>
<!--开启二级缓存(默认为true)-->
<setting name="cacheEnabled" value="true"/>
</settings>
- 打开需要使用二级缓存的mapper的开关
在需要开启二级缓存的mapper.xml中加入caceh标签
<cache/>
- 打开mapper的sql语句缓存开关
<select id="selectUser" parameterType="integer" resultMap="userResultMap" useCache="true">
select user_id,user_name,user_age from user_t where user_id = #{id}
</select>
<!--useCache默认为true-->
映射文件缓存设置
<cache eviction="LRU" flushInterval="60000" size="2" readOnly="true"/>
- eviction是缓存的淘汰算法,可选值有"LRU"、"FIFO"、"SOFT"、"WEAK",缺省值是LRU
LRU:最长时间不使用淘汰
FIFO:先进先淘汰 - flashInterval指缓存过期时间,单位为毫秒,60000即为60秒,缺省值为空,即只要容量足够,永不过期
- size指缓存多少个对象,默认值为1024
- readOnly是否只读,如果为true,则所有相同的sql语句返回的是同一个对象(有助于提高性能,但并发操作同一条数据时,可能不安全),如果设置为false,则相同的sql,后面访问的是cache的clone副本。
// 测试二级缓存对象存储情况(LRU)
@Test
public void testSelectOne3() {
deptDaoImpl.selectOne2(1);// 从库里取且存入缓存
deptDaoImpl.selectOne2(2);// 从库里取且存入缓存
deptDaoImpl.selectOne2(1);// 从缓存取
deptDaoImpl.selectOne2(3);// 从库里取且存入缓存,“2”被挤出
deptDaoImpl.selectOne2(1);// 从缓存取
deptDaoImpl.selectOne2(2);// 从库里取且存入缓存,“3”被挤出
}
/*1,2都在缓存中,为什么2被挤出呢?
因为1比2在最近一次被使用了*/
// 测试二级缓存对象存储情况(FIFO)
@Test
public void testSelectOne4() {
deptDaoImpl.selectOne2(1);// 从库里取存缓存
deptDaoImpl.selectOne2(2);// 从库里取存缓存
deptDaoImpl.selectOne2(1);// 从缓存取
deptDaoImpl.selectOne2(3);// 从库里取,存缓存,“1”被挤出
deptDaoImpl.selectOne2(1);// 从库里取,存缓存,“2”被挤出
deptDaoImpl.selectOne2(2);// 从库里出,存缓存,“3”被挤出
}
/*1,2,3都在缓存中,为什么1被挤出呢?
因为1比2,3都早进入缓存*/