09-Mybatis缓存

12.1 一级缓存

12.1.1 缓存概述

用mybatis从数据库中查询数据,如果有多个用户使用同一个SQL语句来查询记录,得到相同的查询结果。

如果表中记录很多,查询速度比较慢。使用缓存的目的就是为了提升查询的速度。缓存是内存中一个区域,保存已经查询过的记录。

12.1.2 缓存分类

  1. 一级缓存:使用范围是在同一个会话
  2. 二级缓存:可以在不同的会话中使用

12.1.3 缓存结构

**一级缓存的范围:**在同一个会话中使用

需求实现: 通过同一个 sqlSession 对象,通过id查询2次,观察发出 sql 语句的次数。

12.1.4 测试代码

/**
  * 1、在同一个测试方法中查询2次
  * 2、输出用户信息
*/
@Test
public void testFirstLevelCache1(){
    
    
    // 1.打开会话
    session = SessionFactoryUtils.getSession();
    //2.在同一个会话中查询2次,观察SQL语句生成次数
    userMapper = session.getMapper(UserMapper.class);
    // 3.得到用户拓展信息
    UserInfo userInfo1 = userMapper.findUserInfoById(1);
    System.out.println(userInfo1);

    // 4.第二次查询: 使用缓存
    UserInfo userInfo2 = userMapper.findUserInfoById(1);
    System.out.println(userInfo2);
    // 5.关闭会话
    session.close();
}

12.1.5 执行结果

12.1.6 一级缓存的分析

  1. 第1次查询记录,将查询到的数据写入到缓存中

  2. 第2次查询的时候,首先从缓存中去读取数据,如果缓存中有数据,直接返回,而不去访问数据库了。

  3. 如果这个会话执行了添加,修改,删除,提交,关闭清空当前会话的1级缓存。

12.1.7 一级缓存清空

清空的方式:sqlSession 执行添加、修改、删除、提交、关闭等操作,清空 sqlSession 中的一级缓存数据。

清空的目的:为了让缓存中存放最新数据,避免脏读。

12.1.8 测试代码

/**
  * 1、第一次查询以后,提交会话
  * 2、再进行第二次查询,观察查询结果
*/
@Test
public void testFirstLevelCache2(){
    
    
    // 1.打开会话
    session = SessionFactoryUtils.getSession();
    //2.在同一个会话中查询2次,观察SQL语句生成次数
    userMapper = session.getMapper(UserMapper.class);
    // 3.得到用户拓展信息
    UserInfo userInfo1 = userMapper.findUserInfoById(1);
    System.out.println(userInfo1);

    session.commit(); // 提交,清空1级缓存

    // 第二次查询: 使用缓存
    UserInfo userInfo2 = userMapper.findUserInfoById(1);
    System.out.println(userInfo2);
}

12.1.9 执行结果

12.2 二级缓存(XML方式)

范围:在不同的会话中起作用

12.2.1 <cache>标签作用

所有在映射文件里的 select 语句都将被缓存。
所有在映射文件里 insert,update 和 delete 语句会清空缓存。
缓存使用“最近很少使用”算法来回收
每个缓存可以存储 1024 个列表或对象的引用。
缓存获取的对象不是共享的且对调用者是安全的,不会有其它的调用者或线程潜在修改。

12.2.2 实体类要序列化

/**
 用户扩展信息类
 */
public class UserInfo implements Serializable{
    
    
    
}

12.2.3 编写用户接口

/**
* 查询所有的用户拓展信息
*/
List<UserInfo> findAllUserInfo();

12.2.4 sqlMapConfig.xml

<!--开启二级缓存-->
<settings>
    <setting name="cacheEnabled" value="true"/>
</settings>

12.2.5 创建UserMapper.xml

  1. 开启二级缓存
  2. 编写查询语句
<?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="cn.guardwhy.dao.UserMapper">
    <!--当前的映射文件中所有的查询操作使用缓存-->
    <cache/>
    <select id="findAllUserInfo" resultType="userInfo">
        select * from user_info
    </select>
</mapper>

12.2.6 测试代码

@Test
/**
 * 1. 创建一个会话查询1条记录,关闭会话
 * 2. 再创建一个会话查询1条记录,关闭会话
*/
public void testFirstLevelCache3(){
    
    
    // 1.创建第一个会话
    SqlSession session1 = SessionFactoryUtils.getSession();
    UserMapper userMapper1 = session.getMapper(UserMapper.class);
    // 2.得到所有用户拓展信息
    List<UserInfo> userInfos1 = userMapper1.findAllUserInfo();
    // 2.遍历操作
    userInfos1.forEach(System.out::println);
    // 3.关闭会话
    session1.close();

    // 1.创建第一个会话
    SqlSession session2 = SessionFactoryUtils.getSession();
    UserMapper userMapper2 = session.getMapper(UserMapper.class);
    // 2.得到所有用户拓展信息
    List<UserInfo> userInfos2 = userMapper2.findAllUserInfo();
    // 2.遍历操作
    userInfos2.forEach(System.out::println);
    // 3.关闭会话
    session2.close();
}

12.2.7 执行结果

12.3 二级缓存(注解方式)

只需要在UserMapper接口上使用@CacheNamespace对接口中所有的查询方法使用二级缓存

12.3.1 测试代码

package cn.guardwhy.dao;

import cn.guardwhy.domain.OrderForm;
import cn.guardwhy.domain.User;
import cn.guardwhy.domain.UserInfo;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;

import java.util.List;

/**
 * 持久化接口:UserMapper
 */
@CacheNamespace
public interface UserMapper {
    
    

    /**
     * 查询所有的用户拓展信息
    */
    @Select("select * from user_info")
    List<UserInfo> findAllUserInfo();
}

12.3.2 二级缓存分析

猜你喜欢

转载自blog.csdn.net/hxy1625309592/article/details/113528547