mybatis进阶(7)--查询缓存之一级缓存

1.what?
mybatis提供查询缓存,用于减轻数据压力,提高数据库性能
mybatis提供一级缓存,二级缓存
话不多说看图:
这里写图片描述

我们之前的测试中总是需要SQLSession来操作数据库,而这个sqlSession中有这样一个hashmap的数据结构用来存储缓存数据。

不同的sqlSession之间的缓存区域(hashmap)是互不影响的。

二级缓存是mapper级别的缓存,可以跨sqlSession,多个sqlSession去操作数据库会存储在二级缓存区域,多个sqlSession可以共用二级缓存

2.why?
为啥啊?
要是缓存中有我们要的数据就不用在数据库中获取,我们就不用访问系统了,这大大提高了系统的性能。

下图为根据id查询用户的一级缓存图解

这里写图片描述

第一次:
发起查询用户id为1的用户信息,先去缓存中后是否有id为1的用户信息,如果没有,从数据库查询用户信息,并将用户信息存储到一级缓存中去
如果sqlSession去执行commit操作(插入,更新,删除),清空sqlSession的一级缓存,这样是为了让缓存中存储的是最新的信息,避免脏读
第二次:
发起查询用户id为1的用户信息,先去缓存中后是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。

3.how?
mybatis默认提供缓存
来测试下:

@Test
    public void testCache1() throws Exception {
        SqlSession sqlSession=sqlSessionFactory.openSession();
        //获取代理对象
        UserMapper userMapper=sqlSession.getMapper(UserMapper.class);
        //使用一个sqlSession
        //第一次发起请求查询用户id为1的用户
        User u=userMapper.findUserById(1);
        System.out.println(u);
        //第二次发起请求查询用户id为1的用户
        User u2=userMapper.findUserById(1);
        System.out.println(u2);
        sqlSession.close();
    }

来看看结果:

Preparing: SELECT * FROM USER WHERE id=? 
2017-07-18 21:42:58,010 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Parameters: 1(Integer)
2017-07-18 21:42:58,040 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] <==      Total: 1
User [id=1, username=小明, sex=男, birthday=Fri Sep 09 00:00:00 CST 2011, address=北京市海淀区, ordersList=null]
User [id=1, username=小明, sex=男, birthday=Fri Sep 09 00:00:00 CST 2011, address=北京市海淀区, ordersList=null]

可以看出我们的sql代码之发出了一次

那再来测试下更新操作

@Test
    public void testCache1() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        // 获取代理对象
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 使用一个sqlSession
        // 第一次发起请求查询用户id为1的用户
        User u = userMapper.findUserById(1);
        System.out.println(u);

        // 如果sqlSession去执行commit操作(插入,更新,删除),清空sqlSession的一级缓存,这样是为了让缓存中存储的是最新的信息,避免脏读
        u.setUsername("林更新");
        u.setBirthday(new Date());
        u.setSex("男");

        userMapper.updateUser(u);
        sqlSession.commit();

        // 第二次发起请求查询用户id为1的用户
        User u2 = userMapper.findUserById(1);
        System.out.println(u2);
        sqlSession.close();
    }

看下控制台是怎么执行sql的:

Preparing: SELECT * FROM USER WHERE id=? 
2017-07-18 21:49:15,200 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Parameters: 1(Integer)
2017-07-18 21:49:15,231 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] <==      Total: 1
User [id=1, username=小明, sex=男, birthday=Fri Sep 09 00:00:00 CST 2011, address=北京市海淀区, ordersList=null]
2017-07-18 21:49:15,235 [main] [com.ddd.mybatis.mapper.UserMapper.updateUser]-[DEBUG] ==>  Preparing: UPDATE USER SET username=?,birthday=?,sex=?,address=? WHERE id=? 
2017-07-18 21:49:15,237 [main] [com.ddd.mybatis.mapper.UserMapper.updateUser]-[DEBUG] ==> Parameters: 林更新(String), 2017-07-18 21:49:15.234(Timestamp), 男(String), 北京市海淀区(String), 1(Integer)
2017-07-18 21:49:16,201 [main] [com.ddd.mybatis.mapper.UserMapper.updateUser]-[DEBUG] <==    Updates: 1
2017-07-18 21:49:16,201 [main] [org.apache.ibatis.transaction.jdbc.JdbcTransaction]-[DEBUG] Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@5c4d2a5a]
2017-07-18 21:49:16,495 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==>  Preparing: SELECT * FROM USER WHERE id=? 
2017-07-18 21:49:16,495 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] ==> Parameters: 1(Integer)
2017-07-18 21:49:16,497 [main] [com.ddd.mybatis.mapper.UserMapper.findUserById]-[DEBUG] <==      Total: 1
User [id=1, username=林更新, sex=男, birthday=Tue Jul 18 00:00:00 CST 2017, address=北京市海淀区, ordersList=null]

可以看出在commit后缓存清空,第二次查询时,继续发出sql代码访问数据库。

mybatis一级缓存(localcache)的内部是hashmap,他会根据statement的id,还有查询参数动态拼接一个作为key,这样下次如果是相同的key那就直接返回。

4.应用
正式开发是将mybatis和spring整合开发,事务控制在service中
一个service中包括很多mapper方法的调用

service
Service1{
//开始执行时,事务开启,创建sqlSession对象
//第一次调用mapper的方法findUserById(1)

//第二次调用mapper的方法findUserById(1)
//方法结束,sqlSession关闭
}
如果执行2次Service调用查询相同的用户信息,不会走一级缓存,因为service方法结束,sqlSession就关闭,一级缓存就清空

此时就需要二级缓存。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值