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

一级缓存是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。

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

谢谢!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值