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>
相关推荐
醉城夜风~9 分钟前
Java详解经典算法题:接雨水(三种实现方案+原理剖析)
java·开发语言·算法
ck-joker1 小时前
23个测试全绿,一个Token没花——LLM应用的单元测试该怎么写?
语言模型·单元测试
数智化转型推荐官1 小时前
2026统一身份管理系统五大发展趋势解读
java·运维·微服务
看菜鸡互1 小时前
探索用 SlideML 让大模型生成 PPT 的实验方法
java·运维
丑八怪大丑3 小时前
MyBatis
mybatis
程序员张33 小时前
SpringBoot集成BCrypt密码加密库
java·spring boot·后端
闲猫3 小时前
Spring AI Agentic 模式(第1部分):Agent Skills——模块化、可复用的能力
java·人工智能·spring
源图客3 小时前
云途物流API开发-鉴权认证(Java)
java·网络·python
liguojun20254 小时前
篮球馆自动计时收费系统:从规则配置到自动结算的全流程拆解
java·大数据·运维·人工智能·物联网·1024程序员节
952364 小时前
RabbitMQ-基础操作
java·spring boot·分布式·后端·spring·rabbitmq