您的位置:首页 > 编程语言 > Java开发

MyBatis一级缓存和二级缓存实现

2017-09-13 11:25 507 查看
一级缓存是sqlSession的缓存:

//测试一级缓存
@Test
public void testCache1() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();//创建代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

//下边查询使用一个SqlSession
//第一次发起请求,查询id为1的用户
User user1 = userMapper.findUserById(1);
System.out.println("======================"+user1.getUsername());

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

//第二次发起请求,查询id为1的用户
User user2 = userMapper.findUserById(1);
System.out.println("++++++++++++++++++++++"+user2.getUsername());
//sqlSession.commit();
sqlSession.close();

}
再来看看输出:



看看数据库:



结果并没有发生变化

再来试试提交一下:

//测试一级缓存
@Test
public void testCache1() throws Exception{
SqlSession sqlSession = sqlSessionFactory.openSession();//创建代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);

//下边查询使用一个SqlSession
//第一次发起请求,查询id为1的用户
User user1 = userMapper.findUserById(1);
System.out.println("======================"+user1.getUsername());

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

//第二次发起请求,查询id为1的用户
User user2 = userMapper.findUserById(1);
System.out.println("++++++++++++++++++++++"+user2.getUsername());
sqlSession.commit();
sqlSession.close();

}
数据库刷新后:



数据库值更新,同时也清空缓存。

二级缓存是所有sqlSession的缓存,即应用级别的缓存:

//测试二级缓存
@Test
public void testCache2() throws Exception{
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);//创建代理对象
//下边查询使用一个SqlSession
//第一次发起请求,查询id为1的用户
User user1 = userMapper1.findUserById(1);
System.out.println("+++++++++++++++"+user1.getUsername());
//不关闭SqlSession无法写进二级缓存区域中
sqlSession1.close();

UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);//创建代理对象
//第二次发起请求,查询id为1的用户
User user2 = userMapper2.findUserById(1);
System.out.println("================"+user2.getUsername());
sqlSession2.close();

}
再来看看输出:



忽略到输出,那这个就不够严谨了。那我们怎么知道sqlSession2的内容不是从数据库查询的?于是我们将sqlSession1的内容修改、更新、不提交,关闭。

//测试二级缓存
@Test
public void testCache2() throws Exception{
SqlSession sqlSession1 = sqlSessionFactory.openSession();
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);//创建代理对象
//下边查询使用一个SqlSession
//第一次发起请求,查询id为1的用户
User user1 = userMapper1.findUserById(1);
System.out.println("+++++++++++++++"+user1.getUsername());
user1.setUsername("测试");
userMapper1.updateUser(user1);
User user12 = userMapper1.findUserById(1);
System.out.println("---------------"+user12.getUsername());
//不关闭SqlSession无法写进二级缓存区域中
sqlSession1.close();

UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);//创建代理对象
//第二次发起请求,查询id为1的用户
User user2 = userMapper2.findUserById(1);
System.out.println("================"+user2.getUsername());
sqlSession2.close();

}
再来看做过更新后的输出:



命中率为0!

具体什么原因我还没弄明白,等弄明白了再更新!

这里就引用一些以下博客大牛的文章:
http://denger.iteye.com/blog/1126423/
一级缓存基于 PerpetualCache 的
HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该Session中的所有 Cache 就将清空。
二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache、Hazelcast等。
对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。

有希望看源码分析的同行,请移步!

谢谢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  MyBatis缓存 java