MyBatis的缓存!!!!

  • 为什么使用缓存?

    首次访问时,查询数据库,并将数据存储到内存中;再次访问时直接访问缓存,减少IO、硬盘读写次数、提高效率

  • Mybatis中的一级缓存和二级缓存?

    • 一级缓存:

      它指的是mybatis中的SqlSession对象的缓存。当我们执行完查询之后,查询的结果会同时存在在SqlSession为我们提供的一块区域中。当我们再次查询同样的数据,mybatis会先去SqlSession中查询是否有,有的话直接拿出来使用。当SqlSession对象消失时,Mybatis的一级缓存也就消失了。

    • 二级缓存:

      它指的是Mybatis中SqlSessionFactory对象的缓存,由同一个SqlSessioFactory对象创建的SqlSession共享其缓存。

1.一级缓存(默认开启)

(1) 首先在UserMapper接口定义两个方法:

java 复制代码
package com.by.mapper;

import com.by.pojo.User;
import org.apache.ibatis.annotations.Param;
import org.junit.Test;

import java.util.List;

/**
 * <p>Project: mybatis - UserMapper</p>
 * <p>Powered by scl On 2023-12-22 15:52:05</p>
 * <p>描述:<p>
 *
 * @author 孙臣龙 [1846080280@qq.com]
 * @version 1.0
 * @since 17
 */
public interface UserMapper {

    User getUserById(Integer id);

    void deleteUserById(Integer id);
}

(2)在UserMapper.xml文件中实现这两个方法:

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.by.mapper.UserMapper">
    
    <select id="getUserById" parameterType="int" resultType="user">
        select *
        from user
        where id = #{id}
    </select>
    <delete id="deleteUserById" parameterType="int">
        delete
        from user
        where id = #{id};
    </delete>
</mapper>

(3)测试类:

java 复制代码
/*
 * Copyright (c) 2020, 2023,  All rights reserved.
 *
 */
package com.by;

import com.by.mapper.UserMapper;
import com.by.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;


/**
 * <p>Project: mybatis - MyBatisTest</p>
 * <p>Powered by scl On 2023-12-18 11:44:53</p>
 * <p>描述:<p>
 *
 * @author 孙臣龙 [1846080280@qq.com]
 * @version 1.0
 * @since 17
 */
public class MyBatisTestCache {

    private InputStream inputStream;
    private SqlSession sqlSession;

    @Before
    public void init() throws IOException {
         加载配置文件
        //String resource = "mybatis-config.xml";
        //inputStream = Resources.getResourceAsStream(resource);
        //
         创建sqlSessionFActory
        //SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //
         获得数据的绘画实例
        //sqlSession = sessionFactory.openSession();
    }

    /**
     * 一级缓存
     *
     * @throws IOException
     */
    @Test
    public void testFirstGoCache() {

        UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);

        System.out.println("=========One===========");
        User user1 = userMapper1.getUserById(42); // 执行sql语句
        System.out.println(user1);
        System.out.println("=========Two===========");
        User user2 = userMapper2.getUserById(42); // 不执行sql语句,走缓存
        System.out.println(user2);
    }
    /**
     * 一级缓存,不走缓存,同一个sqlSession,中间执行了增删改
     *
     * @throws IOException
     */
    @Test
    public void testFirstNoCache() {

        UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);

        System.out.println("=========One===========");
        User user1 = userMapper1.getUserById(42); // 执行sql语句
        System.out.println(user1);

        System.out.println("========同一个sqlsession之间执行增删改========");
        userMapper1.deleteUserById(41);
        sqlSession.commit();

        System.out.println("=========Two===========");
        User user2 = userMapper2.getUserById(42); // 执行sql语句
        System.out.println(user2);
    }

    /**
     * 一级缓存,不走缓存,不同的sqlSession
     *
     * @throws IOException
     */
    @Test
    public void testFirstNoCache2() throws IOException {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);

        // 创建sqlSessionFActory
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        SqlSession sqlSession1 = sessionFactory.openSession();
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);

        // 获得数据的绘画实例
        SqlSession sqlSession2 = sessionFactory.openSession();
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);

        System.out.println("=========One===========");
        User user1 = userMapper1.getUserById(42); // 执行sql语句
        System.out.println(user1);

        System.out.println("=========Two===========");
        User user2 = userMapper2.getUserById(42); // 执行sql语句
        System.out.println(user2);
    }


    @After
    public void close() throws IOException {
        //inputStream.close();
        //sqlSession.close();
    }

}

2.二级缓存(需要手动开启)

(1)在UserMapper接口中创建两个方法:同上

(2)在UserMapper.xml文件中实现这两个方法:

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.by.mapper.UserMapper">
    <!--局部开启二级缓存-->
    <cache></cache>
    <select id="getUserById" parameterType="int" resultType="user">
        select *
        from user
        where id = #{id}
    </select>
    <delete id="deleteUserById" parameterType="int">
        delete
        from user
        where id = #{id};
    </delete>
</mapper>

(3)测试类:

java 复制代码
/*
 * Copyright (c) 2020, 2023,  All rights reserved.
 *
 */
package com.by;

import com.by.mapper.UserMapper;
import com.by.pojo.User;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;


/**
 * <p>Project: mybatis - MyBatisTest</p>
 * <p>Powered by scl On 2023-12-18 11:44:53</p>
 * <p>描述:<p>
 *
 * @author 孙臣龙 [1846080280@qq.com]
 * @version 1.0
 * @since 17
 */
public class MyBatisTestCache2 {

    private InputStream inputStream;
    private SqlSession sqlSession;

    @Before
    public void init() throws IOException {
         加载配置文件
        //String resource = "mybatis-config.xml";
        //inputStream = Resources.getResourceAsStream(resource);
        //
         创建sqlSessionFActory
        //SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //
         获得数据的绘画实例
        //sqlSession = sessionFactory.openSession();
    }

    /**
     * 二级缓存
     *
     * @throws IOException
     */
    @Test
    public void testSecondGoCache() {
        UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);

        System.out.println("=========One===========");
        User user1 = userMapper1.getUserById(42); // 执行sql语句
        System.out.println(user1);
        sqlSession.commit();
        System.out.println("=========Two===========");
        User user2 = userMapper2.getUserById(42); // 不执行sql语句,走缓存
        System.out.println(user2);
    }

    /**
     * 二级缓存,不走缓存,两个sql之间执行增删改
     *
     * @throws IOException
     */
    @Test
    public void testSecondNoCache() {
        UserMapper userMapper1 = sqlSession.getMapper(UserMapper.class);
        UserMapper userMapper2 = sqlSession.getMapper(UserMapper.class);

        System.out.println("=========One===========");
        User user1 = userMapper1.getUserById(42); // 执行sql语句
        System.out.println(user1);
        sqlSession.commit();

        System.out.println("************增删改**************");
        userMapper1.deleteUserById(41);
        sqlSession.commit();

        System.out.println("=========Two===========");
        User user2 = userMapper2.getUserById(42); // 执行sql语句
        System.out.println(user2);
    }

    /**
     * 二级缓存,不走缓存,不同的sqlSessionFactory
     *
     * @throws IOException
     */
    @Test
    public void testSecondNoCache2() throws IOException {

        String resource = "mybatis-config.xml";
        InputStream inputStream1 = Resources.getResourceAsStream(resource);
        InputStream inputStream2 = Resources.getResourceAsStream(resource);

        //工厂1
        SqlSessionFactory sessionFactory1 = new SqlSessionFactoryBuilder().build(inputStream1);
        SqlSession sqlSession1 = sessionFactory1.openSession();
        UserMapper userMapper1 = sqlSession1.getMapper(UserMapper.class);
        //工厂2
        SqlSessionFactory sessionFactory2 = new SqlSessionFactoryBuilder().build(inputStream2);
        SqlSession sqlSession2 = sessionFactory2.openSession();
        UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);

        System.out.println("=========One===========");
        User user1 = userMapper1.getUserById(42); // 执行sql语句
        System.out.println(user1);
        sqlSession1.commit();

        System.out.println("=========Two===========");
        User user2 = userMapper2.getUserById(42); // 执行sql语句
        System.out.println(user2);
    }


    @After
    public void close() throws IOException {
        //inputStream.close();
        //sqlSession.close();
    }

}

总结:

1、一级缓存

范围:一级缓存范围是sqlSession

配置:默认开启

走缓存:同一个sqlsession执行同一条sql

不走缓存:不同sqlSession 或 两次查询之间执行了增删改

2、二级缓存

范围:二级缓存范围是sqlSessionFactory

配置:<cache></cache>

走缓存:同一个sqlSessionFactrory,sqlsession执行commit或close

不走缓存:不同sqlSessionFactrory 或 两次查询之间执行了增删改

开启缓存:

1.在SqlMapConfig.xml 文件开启二级缓存,默认开启,可以省略

XML 复制代码
<settings>
    <!-- 开启二级缓存的支持 -->
    <setting name="cacheEnabled" value="true"/>
</settings>

2.配置相关的Mapper映射文件 开启局部缓存(必须有)

XML 复制代码
 <!-- 开启二级缓存的支持 -->
    <cache></cache>
相关推荐
huipeng9261 分钟前
第三章线性表+第四章ArrayList与顺序表
java·开发语言
秋恬意6 分钟前
MyBatis动态 SQL 的执行原理
mybatis
ThetaarSofVenice9 分钟前
带着国标充电器出国怎么办? 适配器模式(Adapter Pattern)
java·适配器模式
酷讯网络_24087016014 分钟前
【全开源】Java多语言tiktok跨境商城TikTok内嵌商城送搭建教程
java·开发语言·开源
蓝天星空1 小时前
spring cloud gateway 3
java·spring cloud
罗政1 小时前
PDF书籍《手写调用链监控APM系统-Java版》第9章 插件与链路的结合:Mysql插件实现
java·mysql·pdf
一根稻草君1 小时前
利用poi写一个工具类导出逐级合并的单元格的Excel(通用)
java·excel
kirito学长-Java1 小时前
springboot/ssm网上宠物店系统Java代码编写web宠物用品商城项目
java·spring boot·后端
木头没有瓜1 小时前
ruoyi 请求参数类型不匹配,参数[giftId]要求类型为:‘java.lang.Long‘,但输入值为:‘orderGiftUnionList
android·java·okhttp
奋斗的老史1 小时前
Spring Retry + Redis Watch实现高并发乐观锁
java·redis·spring