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

【Mybatis】二级缓存

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

【Mybatis】二级缓存

目录

二级缓存

如何开启二级缓存?

1.设置全局缓存为true(可省略,因为二级缓存默认开启)

 2.在 SQL 映射文件(mapper)中添加cache标签

3.会话关闭或提交后实现二级缓存

4.增删改会刷新缓存

5.一级缓存、二级缓存、与数据库的联系

缓存机制流程总结:


二级缓存

二级缓存也叫全局缓存,一级缓存作用域(sqlsession级别)太低了,所以诞生了二级缓存基于namespace级别(mapper)的缓存,一个名称空间,对应一个二级缓存

工作机制:
。一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中;
。如果当前会话(sqlsession)关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中;
。新的会话查询信息,就可以从二级缓存中获取内容;
。不同的mapper查出的数据会放在自己对应的缓存(map)中;
 

如何开启二级缓存?

1.设置全局缓存为true(可省略,因为二级缓存默认开启)
    
        
    

 2.在 SQL 映射文件(mapper)中添加cache标签

    
    
        select * from user where id = #{id}
    
    
        update user set pwd = #{pwd},name =#{name} where id = #{id};
    

 默认的效果如下:

  • 映射语句文件中的所有 select 语句的结果将会被缓存。
  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
  • 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
  • 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
  • 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
  • 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

如果使用默认的cache标签,则(只读属性)readOnly默认值为false。也就是可读写,而可读写的缓存会(通过序列化)返回缓存对象的拷贝。 速度上会慢一些,但是更安全。如果是false,则需要让实体类实现序列化接口,否则不能正常读写。出现报错。

3.会话关闭或提交后实现二级缓存

在测试类中,我们每创建一个sqlsession,并实现了它的读操作,关闭后立马创建sqlsession1,保证了在一个时间段里只存在一个sqlsession,也就是说sqlsession关闭后,才将数据存入二级缓存中,从而sqlsession1创建后,从全局缓存(二级缓存)取出数据。

@Test
    public void Test1(){
        SqlSession sqlSession = MyUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.getUserById(1);
        System.out.println(user1);
        sqlSession.close();
        System.out.println("==============");
        SqlSession sqlSession1 = MyUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        User user2 = mapper1.getUserById(1);
        System.out.println(user2);
        sqlSession1.close();
        System.out.println(user1==user2);
    }

可以看到sql只运行了一次,并且第二个会话运行时,是从本地缓存里取得数据,没有执行sql。 false则是因为sqlsession是不同的,因此产生的对象(哈希值)地址值不同。

但是如果像这样:在第一个会话还没关闭之前就运行第二个会话,那么两个会话(线程)都没有关闭,是不会缓存的

 @Test
    public void Test1(){
        SqlSession sqlSession = MyUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.getUserById(1);
        System.out.println(user1);
        System.out.println("==============");
        SqlSession sqlSession1 = MyUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        User user2 = mapper1.getUserById(1);
        System.out.println(user2);
        sqlSession.close();
        sqlSession1.close();
        System.out.println(user1==user2);
    }

 

 所以只需要保证会话关闭后,第二个会话才能从全局缓存中取出数据。 

4.增删改会刷新缓存
@Test
    public void Test1(){
        SqlSession sqlSession = MyUtils.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        User user1 = mapper.getUserById(1);
        System.out.println(user1);
        sqlSession.close();
        System.out.println("==============");
        SqlSession sqlSession1 = MyUtils.getSqlSession();
        UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
        mapper1.updateUserById(new User(2,"xx","14213"));
        sqlSession1.commit();
        System.out.println("==============");
        SqlSession sqlSession2 = MyUtils.getSqlSession();
        UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
        User user2 = mapper2.getUserById(1);
        System.out.println(user2);
        sqlSession2.close();
    }

 

因此增删改无论是对于一级缓存还是二级缓存,都会刷新缓存!

5.一级缓存、二级缓存、与数据库的联系

 

 优先级:二级缓存>一级缓存>数据库

缓存机制流程总结:

先看二级缓存有没有(会话关闭或提交后产生),如果有就拿。如果没有则看一级缓存(在同一个会话里查询后产生)有没有,如果有就拿,没有就去数据库里拿(jdbc预处理对象执行sql)。

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

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

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