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>
相关推荐
打工的小王几秒前
redis(四)搭建哨兵模式:一主二从三哨兵
数据库·redis·缓存
达文汐22 分钟前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
培风图南以星河揽胜23 分钟前
Java版LeetCode热题100之零钱兑换:动态规划经典问题深度解析
java·leetcode·动态规划
启山智软1 小时前
【中大企业选择源码部署商城系统】
java·spring·商城开发
我真的是大笨蛋1 小时前
深度解析InnoDB如何保障Buffer与磁盘数据一致性
java·数据库·sql·mysql·性能优化
怪兽源码1 小时前
基于SpringBoot的选课调查系统
java·spring boot·后端·选课调查系统
恒悦sunsite1 小时前
Redis之配置只读账号
java·redis·bootstrap
梦里小白龙1 小时前
java 通过Minio上传文件
java·开发语言
人道领域1 小时前
javaWeb从入门到进阶(SpringBoot事务管理及AOP)
java·数据库·mysql
sheji52612 小时前
JSP基于信息安全的读书网站79f9s--程序+源码+数据库+调试部署+开发环境
java·开发语言·数据库·算法