一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
2. 二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。作用域为namespance是指对该namespance对应的配置文件中所有的select操作结果都缓存,这样不同线程之间就可以共用二级缓存。
启动二级缓存:在mapper配置文件中:<cache readOnly="true"/>。
3.一级缓存测试实例
/**
* 测试mybatis一级缓存,即session作用域缓存 ( CommandFile 是一个实体类)
*/
@Test
public void testSelect_sessionCache() {
String statement = "com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.select";
SqlSession session = SqlSessionUtil.openSession();
CommandFile commandFile1 = session.selectOne(statement,4l);
CommandFile commandFile2 = session.selectOne(statement,4l);
//commandFile2是从一级缓存中返回的缓存对象,与commandFile1同一个对象实例。
Assert.assertEquals(commandFile1, commandFile2);
//session关闭时清空缓存
session.close();
//显示清空缓存
// session.clearCache();
session = SqlSessionUtil.openSession();
CommandFile commandFile3 = session.selectOne(statement,4l);
//查询时commandFile3,一级缓存已经被清空,commandFile3与commandFile1不是同一个对象实例
Assert.assertNotEquals(commandFile1, commandFile3);
CommandFile commandFile4 = session.selectOne(statement,5l);
//一级缓存中不存在id为5的缓存对象,所以commandFile4是从数据库中查找出的实例。
Assert.assertNotEquals(commandFile3, commandFile4);
}
/**
* 测试mybatis一级缓存,即session作用域缓存 (将session.close()换为执行一个update语句,也会导致一级缓存清空。)
*/
@Test
public void testSelect_sessionCache2() {
String statement = "com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.select";
SqlSession session = SqlSessionUtil.openSession();
CommandFile commandFile1 = session.selectOne(statement,4l);
//执行更新后清空缓存
commandFile1.setName("bigfile-uploader2");
session.update("com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.update",commandFile1);
CommandFile commandFile2 = session.selectOne(statement,4l);
//查询commandFile2时,一级缓存已经被清空,commandFile2与commandFile1不是同一个对象实例
Assert.assertNotEquals(commandFile1, commandFile2);
}
/**
* 测试mybatis二级缓存:nameSpace作用域
* <cache readOnly="false"/>
*/
@Test
public void testSelect_nameSpaceCache() {
String statement = "com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.select";
SqlSession sqlSession1 = SqlSessionUtil.openSession();
SqlSession sqlSession2 = SqlSessionUtil.openSession();
//使用二级缓存时,CommandFile类必须实现一个Serializable接口
CommandFile commandFile1 = sqlSession1.selectOne(statement, 4l);
//sqlSession1提交后才会把数据放到二级缓存中,sqlSession2才能使用二级缓存
sqlSession1.commit();
CommandFile commandFile2 = sqlSession2.selectOne(statement, 4l);
/**
* <cache readOnly="false"/>时,返回缓存对象的拷贝,所以返回的commandFile2 != commandFile1
* 这样一个调用者有修改这个自己的缓存对象时,其他调用者不受影响。
*/
Assert.assertNotEquals(commandFile1, commandFile2);
}
/**
* 测试mybatis二级缓存:nameSpace作用域
* <cache readOnly="true"/>
*/
@Test
public void testSelect_nameSpaceCache2() {
String statement = "com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.select";
SqlSession sqlSession1 = SqlSessionUtil.openSession();
SqlSession sqlSession2 = SqlSessionUtil.openSession();
//使用二级缓存时,CommandFile类必须实现一个Serializable接口
CommandFile commandFile1 = sqlSession1.selectOne(statement, 4l);
//sqlSession1提交后才会把数据放到二级缓存中,sqlSession2才能使用二级缓存
sqlSession1.commit();
CommandFile commandFile2 = sqlSession2.selectOne(statement, 4l);
/**
* <cache readOnly="true"/>时,对所有调用者返回同一个缓存对象,即同一个实例。
* 这样一个调用者有修改这个缓存对象时,其他调用者可能就会出现数据不一致的问题。
*/
Assert.assertEquals(commandFile1, commandFile2);
}
/**
* 测试mybatis二级缓存:nameSpace作用域
* 执行update操作,会清空二级缓存
*/
@Test
public void testSelect_nameSpaceCache3() {
String statement = "com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.select";
SqlSession sqlSession1 = SqlSessionUtil.openSession();
SqlSession sqlSession2 = SqlSessionUtil.openSession();
SqlSession sqlSession3 = SqlSessionUtil.openSession();
//使用二级缓存时,CommandFile类必须实现一个Serializable接口
CommandFile commandFile1 = sqlSession1.selectOne(statement, 4l);
//sqlSession1提交后才会把数据放到二级缓存中,sqlSession2才能使用二级缓存
sqlSession1.commit();
CommandFile commandFile2 = sqlSession2.selectOne(statement, 4l);
/**
* <cache readOnly="true"/>时,对所有调用者返回同一个缓存对象,即同一个实例。
* 这样一个调用者有修改这个缓存对象时,其他调用者可能就会出现数据不一致的问题。
*/
Assert.assertEquals(commandFile1, commandFile2);
commandFile2.setName("bigfile-uploader");
sqlSession2.update("com.xpspeed.centralcms.persist.mybatis.mapper.CommandFileMapper.update", commandFile2);
// 执行commit()表示执行update操作,会清空二级缓存中的数据
sqlSession2.commit();
CommandFile commandFile3 = sqlSession3.selectOne(statement, 4l);
//查询时,二级缓存中没有缓存数据了
Assert.assertNotEquals(commandFile2, commandFile3);
}