栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Mybatis一级缓存

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Mybatis一级缓存

一级缓存定义:
  • Mybatis对缓存提供支持,但是在没有配置的默认情况下,它只开启一级缓存;
  • 一级缓存只是相对于同一个SqlSession而言。在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL;
  • 因为使用SelSession第一次查询后,MyBatis会将其放在缓存中;
  • 以后再查询的时候,如果没有声明需要刷新,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
验证一级缓存:

sql 脚本:

CREATE TABLE `t_user` (
  `f_id` bigint(20) NOT NULL COMMENT 'ID主键',
  `f_user_name` varchar(128) NOT NULL DEFAULT '' COMMENT '用户名字',
  `f_create_time` date DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`f_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';

INSERT INTO `test`.`t_user` (`f_id`, `f_user_name`, `f_create_time`) VALUES ('1', '张三', '2021-09-11');

User.java

@Data
public class User {
    private Long id ;
    private String userName ;
    private Date createTime;
}

UserMapper.java

public interface UserMapper {

    User selectById(Long id);
}

UserMapper.xml





    
        
        
        
    

    


上述代码完成了 对 t_user 单个查询 , 下面让我们看一下测试类:

package com.lot;

import com.alibaba.fastjson.JSONObject;
import com.lot.entity.User;
import lombok.SneakyThrows;
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.Test;

import java.io.InputStream;


public class MybatisStart {

    @SneakyThrows
    @Test
    public void test1() {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        // 获取SqlSession
        SqlSession sqlSession = sqlSessionFactory.openSession();

        // 第一次查询
        User user1 = sqlSession.selectOne("com.lot.mapper.UserMapper.selectById", 1);
        // 打印结果: user1: name:张三
        System.out.println("user1: name:" + user1.getUserName());

        // 在内存中修改 UserName: 张三 -->> 张三1
        user1.setUserName(user1.getUserName() + "1");

        User user2 = sqlSession.selectOne("com.lot.mapper.UserMapper.selectById", 1);
        // 打印结果 user2: name:张三1
        System.out.println("user2: name:" + user2.getUserName());
        sqlSession.close();

        // 新开启一个 SqlSession
        SqlSession sqlSession2 = sqlSessionFactory.openSession();
        User user3 = sqlSession2.selectOne("com.lot.mapper.UserMapper.selectById", 1);
        // 打印结果 user3: name:张三
        System.out.println("user3: name:" + user3.getUserName());

        sqlSession2.close();
    }

}

通过打印结果我们可以得出:
1、同一个 SqlSession,当Sql 和 参数完全一致时,第二次查询会直接从内存中获取,非数据库
2、不同 SqlSession 之间缓存不共享。

带着上述结论,深入MyBatis源码看一下, 究竟是如何实现的。

源码剖析:

如图所示:

  • 我们在第一个SqlSession 第二次查询时加断点:

    先看一下 SqlSession 的对象内的数据

    上图所示:
    当 SqlSession 执行一次Sql查询后会把 执行的 sql 等参数作为 CacheKey, 查询结果作为 value 存放在 HashMap 中,共下次查询使用

Mybatis一级缓存代码流程图如下所示:


ProcessOn 时序图

一级缓存失效:

同一个 SqlSession 中下列操作会导致 一级缓存失效

  • List item
结束:

Mybatis 源码相对比较简单, 一级缓存也是简简单单的存储在 HashMap中,随着 SqlSession 被JVM 回收而回收。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/305820.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号