mybatis-什么是mybatis一级缓存

一、什么是mybatis的一级缓存?

当我们执行相同的sql语句时,mybatis会先查询一级缓存.(二级缓存开启时,会先走二级)减少db访问次数,提升效率.它是session级别的缓存,生命周期是一次会话.session关闭,一级缓存就失效了.

二、通过代码,看现象

1.通过相同的session,和不同的sesssion去访问数据库.

 /**
     * 测试一级缓存需要先关闭二级缓存,localCacheScope设置为SESSION
     * @throws IOException
     */
    @Test
    public void testCache() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        SqlSession session1 = sqlSessionFactory.openSession();
        SqlSession session2 = sqlSessionFactory.openSession();
        try {
            BlogMapper mapper0 = session1.getMapper(BlogMapper.class);
            BlogMapper mapper1 = session1.getMapper(BlogMapper.class);
            Blog blog = mapper0.selectBlogById(1);
            System.out.println(blog);
            System.out.println("------------------------------");
            System.out.println("第二次查询,相同会话,获取到缓存了吗?");
            System.out.println(mapper1.selectBlogById(1));

            System.out.println("------------------------------");
            System.out.println("第三次查询,不同会话,获取到缓存了吗?");
            BlogMapper mapper2 = session2.getMapper(BlogMapper.class);
            System.out.println(mapper2.selectBlogById(1));

        } finally {
            session1.close();
        }
    }

运行结果

在这里插入图片描述
小结:
用同一个session 创建的mapper对象.也就是session1创建的mapper0 和mapper1,mapper1查询的时候没有打印sql语句.也就是走的缓存.而session2创建的mapper2查询打印的sql 语句,也证明一级缓存是session级别.不同的session是不共享的.

2.缓存是是什么时候更新的
我们查询以后,在进行修改,在查询

 /**
     * 一级缓存失效
     * @throws IOException
     */
    @Test
    public void testCacheInvalid() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        SqlSession session = sqlSessionFactory.openSession();
        try {
            BlogMapper mapper = session.getMapper(BlogMapper.class);
            System.out.println(mapper.selectBlogById(1));

            Blog blog = new Blog();
            blog.setBid(1);
            blog.setName("after modified 666");
            mapper.updateByPrimaryKey(blog);
            session.commit();

            // 相同会话执行了更新操作,缓存是否被清空?
            System.out.println("在[同一个会话]执行更新操作之后,是否命中缓存?");
            System.out.println(mapper.selectBlogById(1));

        } finally {
            session.close();
        }
    }

执行结果:
在这里插入图片描述
在修改以后,又打印了sql,说明更新的时候刷新了缓存.(增删改都会删除缓存)

三、缓存的体系结构

mybatis中有一个cache接口.其中的PerpetualCache是一个基础的实现,其他的都是通过包装这个基础的实现,对其功能增强.(装饰器模式)
在这里插入图片描述
PerpetualCache类:
在这里插入图片描述
PerpetualCache中存储缓存的结构就是一个hashmap.

各个装饰缓存的功能
在这里插入图片描述
一级缓存是session级别,那缓存的这个对象是放到哪里的呢,我们猜想是在session,因为这个可以做到,session关闭,缓存也关闭,我们看源码验证一下.

在这里插入图片描述
在默认的session 实现类中,有个2个对象.configuration 是一个全局唯一的对象.缓存对象放在里面不合适.我们看看excutor.

在这里插入图片描述
发现在baseExecutor确实有这个缓存对象.
流程图:

在这里插入图片描述

四、一级缓存有什么问题?

在分布式环境下.多个session可能会查到过时的数据,比如session1查第一次,缓存了数据,这个时候session 修改了session 查询的数据.但是这个时候session1再去查询.还是查询的缓存中的数据.这个时候叫需要二级缓存.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值