• mybatis 15: 缓存


    作用

    • 当对某些数据的查询请求频繁,且数据不经常修改时,使用缓存机制可以提高查询效率

    注意

    • mybatis专注于sql查询,数据映射
    • 缓存问题应该交给专门负责缓存的其他第三方框架

    mybatis缓存执行流程

    image

    mybatis一级和二级缓存

    image

    • 一级缓存作用域:sqlSession对象
    • 二级缓存作用域:Mapper.xml文件
    • 查询顺序:先二级缓存,再一级缓存,最后查数据库

    mybatis一级缓存

    • mybatis默认开启一级缓存

    一级缓存测试

    package com.example.mapper;
    
    import com.example.pojo.User;
    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 java.io.IOException;
    import java.io.InputStream;
    
    public class TestUsersMapper {
    
        //SqlSession对象
        SqlSession sqlSession;
    
        //mybatis动态代理对象
        UsersMapper usersMapper;
    
        //获取SqlSession
        @Before
        public void getSqlSession() throws IOException {
            //读取核心配置文件
            InputStream in = Resources.getResourceAsStream("SqlMapConfig.xml");
            //创建SqlSessionFactory对象
            SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(in);
            //获取SqlSession
            sqlSession = factory.openSession();
            //获取mybatis动态代理对象
            usersMapper = sqlSession.getMapper(UsersMapper.class);
        }
    
        //归还SqlSession
        @After
        public void closeSession(){
            sqlSession.close();
        }
    
        //测试mybatis一级缓存
        @Test
        public void testOneLevelCache(){
            //两次查询,id相同时
            User u1 = usersMapper.getById(1);
            System.out.println("第1次查询结果: " + u1);
            System.out.println("----------------------");
            User u2 = usersMapper.getById(1);
            System.out.println("第2次查询结果: " + u2);
            System.out.println("------------------------");
            if(u1 == u2){
                System.out.println("两个对象的内存地址相同");
            }else{
                System.out.println("两个对象的内存地址不同");
            }
            System.out.println("**************************************************");
            //两次查询,id不同时
            User u3 = usersMapper.getById(2);
            System.out.println("第1次查询结果: " + u3);
            System.out.println("----------------------");
            User u4 = usersMapper.getById(5);
            System.out.println("第2次查询结果: " + u4);
            System.out.println("------------------------");
            if(u3 == u4){
                System.out.println("两个对象的内存地址相同");
            }else{
                System.out.println("两个对象的内存地址不同");
            }
        }
    }
    

    测试结果

    ==>  Preparing: select id, username, birthday, sex, address from users where id=?
    ==> Parameters: 1(Integer)
    <==    Columns: id, username, birthday, sex, address
    <==        Row: 1, 荷包蛋, 2002-08-23, 女, 黑河
    <==      Total: 11次查询结果: Users{id=1, userName='荷包蛋', birthday=Fri Aug 23 00:00:00 CST 2002, sex='女', address='黑河'}
    ----------------------
    第2次查询结果: Users{id=1, userName='荷包蛋', birthday=Fri Aug 23 00:00:00 CST 2002, sex='女', address='黑河'}
    ------------------------
    两个对象的内存地址相同
    **************************************************
    ==>  Preparing: select id, username, birthday, sex, address from users where id=?
    ==> Parameters: 2(Integer)
    <==    Columns: id, username, birthday, sex, address
    <==        Row: 2, 小王, 2001-07-12, 1, 芜湖市
    <==      Total: 11次查询结果: Users{id=2, userName='小王', birthday=Thu Jul 12 00:00:00 CST 2001, sex='1', address='芜湖市'}
    ----------------------
    ==>  Preparing: select id, username, birthday, sex, address from users where id=?
    ==> Parameters: 5(Integer)
    <==    Columns: id, username, birthday, sex, address
    <==        Row: 5, 段, 2001-03-10, 1, 太原
    <==      Total: 12次查询结果: Users{id=5, userName='段', birthday=Sat Mar 10 00:00:00 CST 2001, sex='1', address='太原'}
    ------------------------
    两个对象的内存地址不同
    

    结果分析

    • 以上u1到u4同属于一个sqlSession域,因为下面代码只执行过一次,sqlSession只获取过一个,后面操作都是在该sqlSession对象的基础上进行的
    //获取SqlSession
    sqlSession = factory.openSession();
    
    • 当两次查询的id相同时,第一次查询开启了数据库连接,第二次没有再开启数据库连接,而是从缓存中获取,且两个对象内存地址相同
      • 其实u1和u2本质上是sqlSession域中的同一个对象
    • 当两次查询的id不同时,两次查询都开启了数据库连接,且两个对象内存地址不同
      • 其实u3和u4本质上是sqlSession域中的不同对象
  • 相关阅读:
    浅谈智慧水务在供水厂企业中的应用发展-Susie 周
    POJ2676Sudoku题解
    PyQt5_股票K线图相似度工具
    校园篮球网页作业成品 运动系列NBA篮球主题 学校篮球网页制作模板 学生简单体育运动网站设计成品
    二手物品交易管理系统
    Python网络爬虫入门篇
    代码随想录 | Day 60(完结) - LeetCode 84. 柱状图中最大的矩形
    【Swift算法学习】 LeetCode 同构字符串
    hadoop使用简介
    win10的快捷键&GPU
  • 原文地址:https://www.cnblogs.com/nefu-wangxun/p/16595127.html