首页 > 其他分享 >详解Mybatis一级缓存和二级缓存

详解Mybatis一级缓存和二级缓存

时间:2023-07-04 22:45:49浏览次数:41  
标签:缓存 一级 sqlsession 查询 二级缓存 SqlSession Mybatis

mybatis包含了一个非常强大的查询缓存特性,他可以非常方便的定制和配置缓存。缓存可以极大的提高查询的效率

mybatis系统当中默认定义了两级缓存:一级缓存和二级缓存

一级缓存:默认情况之下,只有一级缓存开启(sqlSession级别的缓存)

二级缓存:需要手动开启配置,需要局域namespace级别的缓存。

一级缓存失效的场景:

sqlSession不同sqlSession相同,查询条件不同sqlSession相同,两次查询之间执行了增删改操作!sqlSession相同,手动清除一级缓存
1.mybatis一级缓存是SqlSession级别的缓存,2.在操作数据库的时候需要构造sqlsession对象,在对象中有一个数据结构(HashMap)用于存储数据。3.不同的Sqlsession之间的缓存数据区域是互相不影响的,是独立的4.一级缓存是框架默认为我们开启的,我们不需要做任何配置//key:statementId和sql语句//value:查询结果

一级缓存是sqlsession级别的缓存,也叫本机缓存,因为每一个用户来执行查询的时候都需要sqlsession来执行。为了避免每次都去查询数据库。mybatis把缓存的数据存到sqlsession的本地缓存里面,如果sqlsession里面有的可以直接从本地缓存去读取查询的数据。要是想实现跨Ssqlsession这个级别的话,需要用到二级缓存。就是当多个用户去查询数据的时候,只要有任何一个sqlsession拿到了数据,就会放入到二级缓存里面,其它的sqlsession可以直接从二级缓存里面查询数据。

需要注意的是,如果SqlSession执行了DML操作(增删改),并且提交到数据库,MyBatis则会清空SqlSession中的一级缓存,这样做的目的是为了保证缓存中存储的是最新的信息,避免出现脏读现象

二级缓存:
二级缓存是mapper级别的缓存,多个Sqlsession去操作一个mapper.xml语句,多个sqlseesion共用一个二级缓存,//key:hashCode + statementId + SQL语句//value:查询结果
二级缓存开启步骤:
<!‐‐ 开启二级缓存 ‐‐><settings>    <!--开启二级缓存-->    <setting name="cacheEnabled" value="true"/></settings>
<!--使用二级缓存--><cache eviction="FIFO" #收回策略        flushInterval="6000" #刷新间隔        size="512" #引用数目        readOnly="true"/> #只读

eviction回收策略:

LRU(最近最少使用的):移除最长时间不被使用的对象,这是默认值。

FIFO(先进先出):按对象进入缓存的顺序来移除它们。

SOFT(软引用):移除基于垃圾回收器状态和软引用规则的对象。

WEAK(弱引用):更积极地移除基于垃圾收集器状态和弱引用规则的对象。

flushinterval(刷新间隔)

​可以被设置为任意的正整数,而且它们代表一个合理的毫秒形式的时间段。

默认情况不设置,即没有刷新间隔,缓存仅仅在调用语句时刷新。

size(引用数目)

可以被设置为任意正整数,要记住缓存的对象数目和运行环境的可用内存资源数目。默认值是1024 。

readOnly(只读)​

属性可以被设置为 true 或 false。只读的缓存会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改, 这提供了很重要的性能优势。

可读写的缓存会通过序列化返回缓存对象的拷贝,这种方式会慢一些,但是安全,因此默认是 false。

④. 在select标签上使用二级缓存

<select id="findById" parameterType="int" resultType="User" useCache="true" >select * from user where id = #{id}</select>

二级缓存测试:

public class UserTest {    private InputStream in = null;    private SqlSession session1 = null;    private SqlSession session2 = null;    private UserDao mapper1 = null;    private UserDao mapper2 = null;    @Test    public void findById() throws IOException {        // 1.加载SqlMapConfig配置文件        InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");        //2.创建sqlSessionFactory工厂        SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(resourceAsStream);        //3.sqlSessionFactory创建sqlSession        SqlSession sqlSession1 = factory.openSession();        SqlSession sqlSession2 = factory.openSession();        //4.通过Session创建UserDao接口代理对象        UserDao mapper1 = sqlSession1.getMapper(UserDao.class);        UserDao mapper2 = sqlSession2.getMapper(UserDao.class);        User user1 = mapper1.find(1);        System.out.println(user1.toString());        // 将其一级缓存的数据放进二级缓存中,并清空一级缓存        sqlSession1.commit();        System.out.println("-----------------");        User user2 = mapper2.find(1);        System.out.println(user2.toString());        System.out.println(user1 == user2);        // 将其一级缓存的数据放进二级缓存中,并清空一级缓存        sqlSession2.commit();        //7.关闭资源        sqlSession1.close();        sqlSession2.close();        resourceAsStream.close();    }}

1、一级缓存和二级缓存原理

在sqlsession里面会有一个 executor,每一个executor里面会有一个localcache对象,当用户发起查询的时候,mybatis会根据执行语句,在localcache去查找,如果命中了就直接把这个数据返回,没有的话,再去数据库里面查找出来,ch再写入到localcae里面。所以一级缓存的生命周期是sqlsession。

需要注意的是,在多个sqlsession或者分布式环境下,可能会因为一级缓存,导致一个脏读的情况。

2、二级缓存实现原理是在executor上,引入了一个叫cachingexecutor的一个装饰器, 所以在进入一级缓存之前,会先通过cachingexecutor进行二级缓存 的查询。开启二级缓存之后会被多个sqlsession共享。所以它是一个全局的缓存。所以它的查询流程就变成了先查二级缓存,再查一级缓存,然后再去查数据库。

mybatis的二级缓存相当一级缓存来说,它实现了sqlsession之间缓存数据的一个共享,同时缓存粒度,也能控制到namespace一个级别,并且还通过cache这样的一个接口,来实现不同缓存实现类的一个组合, 对cache的可控也更高了。

关注关注了解更多:

 

标签:缓存,一级,sqlsession,查询,二级缓存,SqlSession,Mybatis
From: https://www.cnblogs.com/liubaihui/p/17527262.html

相关文章

  • 接口缓存、定时更新、异步发送短信
    目录一、接口缓存二、双写一致性之定时更新celery的定时任务代码celery_task/home_task.pycelery_task/celery.py启动worker、beta三、异步发送短信步骤视图函数user/views.py任务celery_task/user_task.py四、异步秒杀逻辑前后端4.1前端Sckill.vue4.2后端视图类路由任务:celery......
  • 如何保持缓存和数据库中的数据一致
    背景缓存是软件开发中一个非常有用的概念,数据库缓存更是在项目中必然会遇到的场景。而缓存一致性的保证,更是在面试中被反复问到,这里进行一下总结,针对不同的要求,选择恰到好处的一致性方案。缓存是什么存储的速度是有区别的。缓存就是把低速存储的结果,临时保存在高速存储的技术。......
  • mybatis的原理
    MyBatis是一个持久层框架,它的工作原理是:1.首先,MyBatis从XML映射文件中读取SQL语句,将其解析成SQL语句对象,并将SQL语句对象存储在内存中。2.然后,MyBatis将SQL语句对象与用户提供的参数绑定,生成完整的SQL语句。3.接着,MyBatis将SQL语句发送给数据库,并将查询结果映射到Jav......
  • hibernate和mybatis的区别
    Hibernate和MyBatis都是目前业界中主流的对象关系映射(ORM)框架,它们的主要区别如下。1)sql优化方面Hibernate使用HQL(HibernateQueryLanguage)语句,独立于数据库。不需要编写大量的SQL,就可以完全映射,但会多消耗性能,且开发人员不能自主的进行SQL性能优化。提供了日志、缓存......
  • 基于Redis分布式缓存
    1.安装包使用Redis分布式缓存需要安装Redis的支持包,可以通过nuget命令安装,如下:install-packageMicrosoft.Extensions.Caching.StackExchangeRedis 2.在Program.cs文件中注册builder.Services.AddStackExchangeRedisCache(option=>{option.Configuration......
  • Vue内置缓存组件keep-alive
    <el-tab-panelabel="周边配套":disabled=!gardenIdname="five"><keep-alive><Surrour:gardenId="gardenId"v-if="activeName==='five'"/></keep-alive>......
  • MyBatis
    MyBatis是一款优秀的持久层框架,用于简化JDBC开发官网:https://mybatis.org/mybatis-3/zh/index.html持久层负责将数据到保存到数据库的那一层代码JavaEE三层架构:表现层、业务层、持久层框架框架就是一个半成品软件,是一套可重用的、通用的、软件基础代码模型在框......
  • 从 JDBC 到 Mybatis
    JDBC操作数据库流程1、加载驱动2、获取数据库连接3、获取执行者对象4、执行sql语句并返回结果5、处理结果代码publicclassJDBCTest{publicstaticvoidmain(String[]args)throwsClassNotFoundException,SQLException{//注册驱动C......
  • Flask插件---flask-caching (缓存)
    Flask插件---flask-caching(缓存)安装pipinstallflask-caching加载配置插件在exts.py文件中配置#exts.py:插件管理#扩展的第三方插件#1.导入第三方插件fromflask_sqlalchemyimportSQLAlchemyfromflask_migrateimportMigratefromflask_cachingimportC......
  • 03_MyBatis02
    1.深入Mybatis映射配置文件1.1.CRUD语句定义查询语句UserMapper.java接口中publicList<User>queryAllUser();publicUserqueryUserById(Integerid);UserMapper.xml配置文件中<selectid="queryAllUser"resultType="uSer"> select*fromuser;</......