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>
相关推荐
代码之光_198038 分钟前
保障性住房管理:SpringBoot技术优势分析
java·spring boot·后端
ajsbxi44 分钟前
苍穹外卖学习记录
java·笔记·后端·学习·nginx·spring·servlet
StayInLove1 小时前
G1垃圾回收器日志详解
java·开发语言
对许1 小时前
SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder“
java·log4j
鹿屿二向箔1 小时前
基于SSM(Spring + Spring MVC + MyBatis)框架的咖啡馆管理系统
spring·mvc·mybatis
无尽的大道1 小时前
Java字符串深度解析:String的实现、常量池与性能优化
java·开发语言·性能优化
小鑫记得努力1 小时前
Java类和对象(下篇)
java
binishuaio1 小时前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE1 小时前
【Java SE】StringBuffer
java·开发语言
老友@1 小时前
aspose如何获取PPT放映页“切换”的“持续时间”值
java·powerpoint·aspose