MyBatis(8)——缓存

1.1 缓存简介

查询 : 连接数据库,耗资源
​ 一次查询的结果,给他暂存一个可以直接取到的地方 --> 内存:缓存
我们再次查询的相同数据的时候,直接走缓存,不走数据库了
什么是缓存?

  • 存在内存中的临时数据。
  • 将用户经常查询的数据放在缓存(内存)中,用户去查询数据就不用从磁盘上(关系型数据库数据文件)查询,从缓存中查询,从而提高查询效率,解决了高并发系统的性能问题。

为什么使用缓存
减少和数据库的交互次数,减少系统开销,提高系统效率。

什么样的数据能使用缓存
经常查询并且不经常改变的数据。

1.2 Mybatis缓存

  • MyBatis系统中默认定义了两级缓存:一级缓存和二级缓存。
  • 默认情况下,只有一级缓存开启。(SqlSession级别的缓存,也称为本地缓存)
  • 二级缓存需要手动开启和配置,他是基于namespace级别的缓存(一个mapper 一个接口)。
  • 为了提高扩展性,MyBatis定义了缓存接口Cache。我们可以通过实现Cache接口来自定义二级缓存。

1.2.1 一级缓存

一级缓存也叫本地缓存。与数据库同一次会话期间查询到的数据会放在本地缓存中。以后如果需要获取相同的数据,直接从缓存中拿,没必须再去查询数据库。默认是开启的。

测试
1 编写接口方法

Blog queryUserById(@Param("id") int id);

2 mapper.xml文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxxx.dao.BlogMapper">
    <select id="queryUserById" resultType="com.xxxx.pojo.Blog">
        select * from blog where id = #{
    
    id}
    </select>
</mapper>

3 测试

package com.xxxx.dao;

import com.xxxx.pojo.Blog;
import com.xxxx.utils.IDUtil;
import com.xxxx.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.*;


public class DaoTest {
    
    
    //注意导包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
    
    
       try(SqlSession session = MyBatisUtils.getSqlSesion();){
    
    
           BlogMapper mapper = session.getMapper(BlogMapper.class);
           Blog blog = mapper.queryUserById(1);
           System.out.println(blog);
           System.out.println("===========================");
           Blog blog2 = mapper.queryUserById(1);
           System.out.println(blog2);

           System.out.println(blog == blog2);
       }
    }
}

在这里插入图片描述
分析: sql语句只执行了一次,并且用的是同一个对象。

1.2.2 一级缓存失效的四种情况

1、sqlSession不同

package com.xxxx.dao;

import com.xxxx.pojo.Blog;
import com.xxxx.utils.IDUtil;
import com.xxxx.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.*;


public class DaoTest {
    
    
    //注意导包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
    
    
       try(SqlSession session1 = MyBatisUtils.getSqlSesion();
           SqlSession session2 = MyBatisUtils.getSqlSesion();
       ){
    
    
           BlogMapper mapper1 = session1.getMapper(BlogMapper.class);
           Blog blog1 = mapper1.queryUserById(1);
           System.out.println(blog1);
           System.out.println("===========================");
           BlogMapper mapper2 = session2.getMapper(BlogMapper.class);
           Blog blog2 = mapper2.queryUserById(1);
           System.out.println(blog2);

           System.out.println(blog1 == blog2);
       }
    }
}

在这里插入图片描述
分析:每个sqlSession中的缓存相互独立

2、sqlSession相同,查询条件不同

package com.xxxx.dao;

import com.xxxx.pojo.Blog;
import com.xxxx.utils.IDUtil;
import com.xxxx.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.*;


public class DaoTest {
    
    
    //注意导包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
    
    
       try(SqlSession session1 = MyBatisUtils.getSqlSesion();){
    
    
           BlogMapper mapper1 = session1.getMapper(BlogMapper.class);
           Blog blog1 = mapper1.queryUserById(1);
           System.out.println(blog1);
           System.out.println("===========================");

           Blog blog2 = mapper1.queryUserById(2);
           System.out.println(blog2);

           System.out.println(blog1 == blog2);
       }
    }
}

在这里插入图片描述
分析:当前缓存中,不存在这个数据

3、sqlSession相同,两次查询之间执行了增删改操作!

package com.xxxx.dao;

import com.xxxx.pojo.Blog;
import com.xxxx.utils.IDUtil;
import com.xxxx.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.*;


public class DaoTest {
    
    
    //注意导包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
    
    
       try(SqlSession session1 = MyBatisUtils.getSqlSesion();){
    
    
           BlogMapper mapper1 = session1.getMapper(BlogMapper.class);
           Blog blog1 = mapper1.queryUserById(1);
           System.out.println(blog1);
           System.out.println("===========================");
           Map map = new HashMap();
           map.put("id" , "3");
           map.put("author" , "xinxue");

           mapper1.updateUserById(map);

           System.out.println("===========================");

           Blog blog2 = mapper1.queryUserById(1);
           System.out.println(blog2);

           System.out.println(blog1 == blog2);
       }
    }
}

在这里插入图片描述
分析:因为增删改操作可能会对当前数据产生影响

4 、sqlSession相同,手动清除一级缓存

package com.xxxx.dao;

import com.xxxx.pojo.Blog;
import com.xxxx.utils.IDUtil;
import com.xxxx.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.*;


public class DaoTest {
    
    
    //注意导包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
    
    
       try(SqlSession session1 = MyBatisUtils.getSqlSesion();){
    
    
           BlogMapper mapper1 = session1.getMapper(BlogMapper.class);
           Blog blog1 = mapper1.queryUserById(1);
           System.out.println(blog1);
           System.out.println("===========================");
           session1.clearCache();

           Blog blog2 = mapper1.queryUserById(1);
           System.out.println(blog2);

           System.out.println(blog1 == blog2);
       }
    }
}

在这里插入图片描述

1.2.2 二级缓存

在这里插入图片描述

  • 二级缓存也叫全局缓存,一级缓存作用域太低了,所以诞生了二级缓存。
  • 基于namespace级别的缓存,一个名称空间,对应一个二级缓存。
  • 工作机制:
    一个会话查询一条数据,这个数据就会被放在当前会话的一级缓存中
    如果当前会话关闭了,这个会话对应的一级缓存就没了;但是我们想要的是,会话关闭了,一级缓存中的数据被保存到二级缓存中
    新的会话查询信息,就可以从二级缓存中获取内容
    不同的mapper查出的数据会放在自己对应的缓存(map)中

使用步骤
1、开启全局缓存 【mybatis-config.xml】

<!--    开启全局缓存机制 默认就是开启的-->
        <setting name="cacheEnabled" value="true"/>

2、去每个mapper.xml中配置使用二级缓存

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xxxx.dao.BlogMapper">
    
    **<cache
            eviction="FIFO"
            flushInterval="60000"
            size="512"
            readOnly="true"/>**
    
    <select id="queryUserById" resultType="com.xxxx.pojo.Blog">
        select * from blog where id = #{
    
    id}
    </select>

    <update id="updateUserById" parameterType="map">
        update blog set author = #{
    
    author} where id = #{
    
    id}
    </update>
</mapper>

3、代码测试
所有的实体类先实现序列化接口

package com.xxxx.dao;

import com.xxxx.pojo.Blog;
import com.xxxx.utils.IDUtil;
import com.xxxx.utils.MyBatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;
import org.junit.Test;

import java.util.*;


public class DaoTest {
    
    
    //注意导包:org.apache.log4j.Logger
    static Logger logger = Logger.getLogger(DaoTest.class);
    @Test
    public  void test(){
    
    
        SqlSession session1 = MyBatisUtils.getSqlSesion();
        SqlSession session2 = MyBatisUtils.getSqlSesion();
        BlogMapper mapper1 = session1.getMapper(BlogMapper.class);
        BlogMapper mapper2 = session2.getMapper(BlogMapper.class);

        Blog blog = mapper1.queryUserById(1);
        System.out.println(blog);
        session1.close();
        System.out.println("=========================");

        Blog blog1 = mapper2.queryUserById(1);
        System.out.println(blog1);
        session2.close();
    }
}

在这里插入图片描述
1 只要开启了二级缓存,我们在同一个Mapper【namespace】中的查询,可以在二级缓存中拿到数据
2 查出的数据都会被默认先放在一级缓存中
3 只有会话提交或者关闭以后,一级缓存中的数据才会转到二级缓存中

1.2.3 缓存原理

1. 用户先查二级缓存
2. 再查询一级缓存
3. 最后查询数据库

猜你喜欢

转载自blog.csdn.net/zs18753479279/article/details/110939999