为了账号安全,请及时绑定邮箱和手机立即绑定

MyBatis3.2.x从入门到精通之第九章

这一章我想分成两节,分别讲解一级缓存和二级缓存。

  1. 什么是查询缓存?
    mybatis提供查询缓存,用于减轻数据压力,提高数据库性能。
    mybatis提供一级缓存和二级缓存。
  2. 如图:
    缓存结构图
    一级缓存:是SqlSession级别的缓存。在操作数据库时需要构造 sqlSession对象,在对象中有一个数据结构(HashMap)用于存储缓存数据。不同的sqlSession之间的缓存数据区域(HashMap)是互相不影响的。
    二级缓存:是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。
  3. 为什么要使用缓存?
    如果缓存中有数据就不用从数据库中获取,大大提高系统性能。
    一级缓存原理:
    一级缓存原理
    说明:
    第一次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,如果没有,从数据库查询用户信息。
    得到用户信息,将用户信息存储到一级缓存中。
    如果sqlSession去执行commit操作(执行插入、更新、删除),清空SqlSession中的一级缓存,这样做的目的为了让缓存中存储的是最新的信息,避免脏读。
    第二次发起查询用户id为1的用户信息,先去找缓存中是否有id为1的用户信息,缓存中有,直接从缓存中获取用户信息。
    测试:
    mybatis默认支持一级缓存,所以不需要配置
    看下测试代码:
package cn.mybatis.mapper.test;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import cn.mybatis.mapper.UserMapper;
import cn.mybatis.pojo.User;

public class UserMapperTest {
    private SqlSessionFactory sqlSessionFactory;
    private SqlSession sqlSession;

    @Before
    public void setUp() throws Exception {
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources
                .getResourceAsStream("MyBatisConfig.xml"));
        sqlSession = sqlSessionFactory.openSession();
    }

    @After
    public void tearDown() throws Exception {
        sqlSession.close();
    }

    @Test
    // 一级缓存测试
    public void testFindUserById() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 第一次发出请求
        Long beginTimes = System.currentTimeMillis();
        User user1 = userMapper.findUserById(1);
        Long endTimes = System.currentTimeMillis();
        System.out.println(user1);
        System.out.println("第一次请求,共花费:" + (endTimes - beginTimes));

        // 第二次发出请求
        Long beginTimes2 = System.currentTimeMillis();
        User user2 = userMapper.findUserById(1);
        Long endTimes2 = System.currentTimeMillis();
        System.out.println(user2);
        System.out.println("第二次请求,共花费:" + (endTimes2 - beginTimes2));

    }
}

输出结果分别是:

User [id=1, username=紫衫龙王, sex=2, birthday=Mon Sep 14 00:00:00 CST 2015, address=盐城]
第一次请求,共花费:320
User [id=1, username=紫衫龙王, sex=2, birthday=Mon Sep 14 00:00:00 CST 2015, address=盐城]
第二次请求,共花费:0

结果很明显了,就不用多说了。
第二种情况:更新下数据commit一下

    @Test
    public void testUpdateUser() throws Exception {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        // 1、第一次请求
        Long beginTimes = System.currentTimeMillis();
        User user1 = userMapper.findUserById(1);
        Long endTimes = System.currentTimeMillis();
        System.out.println(user1);
        System.out.println("第一次请求,共花费:" + (endTimes - beginTimes));
        // 更新数据
        user1.setUsername("紫衫龙王");//金毛狮王、轻翼蝠王、紫衫龙王
        Long beginTimes3 = System.currentTimeMillis();
        userMapper.updateUser(user1);
        Long endTimes3 = System.currentTimeMillis();
        System.out.println("更新,共花费:" + (endTimes3 - beginTimes3));
        System.out.println(user1);
        // 清空缓存
        sqlSession.commit();
        // 2、第二次请求
        Long beginTimes2 = System.currentTimeMillis();
        User user2 = userMapper.findUserById(1);
        Long endTimes2 = System.currentTimeMillis();
        System.out.println(user2);
        System.out.println("第二次共花费:" + (endTimes2 - beginTimes2));

    }

运行结果:

User [id=1, username=紫衫龙王, sex=2, birthday=Mon Sep 14 00:00:00 CST 2015, address=盐城]
第一次请求,共花费:300
2016-04-06 15:37:59,880 [main] DEBUG [cn.mybatis.mapper.UserMapper.updateUser] - ==>  Preparing: update user set username=?,birthday=?,sex=?,address=? where id=? 
  2016-04-06 15:37:59,884 [main] DEBUG [cn.mybatis.mapper.UserMapper.updateUser] - ==> Parameters: 紫衫龙王(String), 2015-09-14 00:00:00.0(Timestamp), 2(String), 盐城(String), 1(Integer)
  2016-04-06 15:37:59,885 [main] DEBUG [cn.mybatis.mapper.UserMapper.updateUser] - <==    Updates: 1
  更新,共花费:6
User [id=1, username=紫衫龙王, sex=2, birthday=Mon Sep 14 00:00:00 CST 2015, address=盐城]
2016-04-06 15:37:59,964 [main] DEBUG [cn.mybatis.mapper.UserMapper.findUserById] - ==>  Preparing: select * from user where id = ? 
  2016-04-06 15:37:59,964 [main] DEBUG [cn.mybatis.mapper.UserMapper.findUserById] - ==> Parameters: 1(Integer)
  2016-04-06 15:37:59,965 [main] DEBUG [cn.mybatis.mapper.UserMapper.findUserById] - <==      Total: 1
  User [id=1, username=紫衫龙王, sex=2, birthday=Mon Sep 14 00:00:00 CST 2015, address=盐城]
第二次共花费:1

虽然只有1mm,但也是去查询的毕竟大部分数据没有变动只是改了一个名字。
一级缓存应用:
正式开发,是将mybatis和spring进行整合开发,事务控制在service中。
一个service方法中包括很多mapper方法调用。
service{
//开始执行时,开启事务,创建SqlSession对象
//第一次调用mapper的方法findUserById(1)

     //第二次调用mapper的方法findUserById(1),从一级缓存中取数据
     //方法结束,sqlSession关闭

}
如果是执行两次service调用查询相同的用户信息,不走一级缓存,因为session方法结束,sqlSession就关闭,一级缓存就清空。

点击查看更多内容
18人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
JAVA开发工程师
手记
粉丝
334
获赞与收藏
3452

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消