MyBatis的缓存分为一级缓存和二级缓存。

先看一下MyBatis官方文档给出的说明:

MyBatis 内置了一个强大的事务性查询缓存机制,它可以非常方便地配置和定制。 为了使它更加强大而且易于配置,我们对 MyBatis 3 中的缓存实现进行了许多改进。

默认情况下,只启用了本地的会话缓存,它仅仅对一个会话中的数据进行缓存。 要启用全局的二级缓存,只需要在你的 SQL 映射文件中添加一行:

基本上就是这样。这个简单语句的效果如下:

  • 映射语句文件中的所有 select 语句的结果将会被缓存。
  • 映射语句文件中的所有 insert、update 和 delete 语句会刷新缓存。
  • 缓存会使用最近最少使用算法(LRU, Least Recently Used)算法来清除不需要的缓存。
  • 缓存不会定时进行刷新(也就是说,没有刷新间隔)。
  • 缓存会保存列表或对象(无论查询方法返回哪种)的 1024 个引用。
  • 缓存会被视为读/写缓存,这意味着获取到的对象并不是共享的,可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改。

这里我们来学习一级缓存。

一级缓存也叫本地缓存,是在一次SqlSession会话中产生的缓存,在一次SqlSession会话中查询到的数据存入缓存中,再次执行相同的查询就不需要再从数据库获取数据,而是直接从本地获取。

下面我们用一个实例来说明:

UserMapper接口:

package com.jms.dao;import com.jms.pojo.User;public interface UserMapper {    User getUserById(int id);}

UserMapper.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.jms.dao.UserMapper">    <select id="getUserById" parameterType="_int" resultType="User">        select * from mybaties.user where id=#{id}    </select></mapper>

测试:

@Test    public void getUserById() {        SqlSession sqlSession = MyBatisUtil.getSqlSession();        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);        User user = userMapper.getUserById(10001);        System.out.println(user);        System.out.println("=========================================");        User user2 = userMapper.getUserById(10001);        System.out.println(user2);        sqlSession.close();    }

测试结果:

可以看见只有第一次查询进入了数据库进行查询,第二次获取相同数据则没有进入数据库查询,是因为它直接从缓存中获取了数据。

明白了一级缓存的使用,那么什么情况下一级缓存会失效呢?

1.不同的SqlSession。一级缓存只在一次SqlSession中生效,不同的SqlSession中相同的查询也无法从缓存中获取。

2.执行增删改语句后,会刷新缓存。增删改有改变数据的可能,缓存的刷新是必然的。

3.使用清除缓存的命令

SqlSession.clearCache();
@Test    public void getUserById() {        SqlSession sqlSession = MyBatisUtil.getSqlSession();        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);        User user = userMapper.getUserById(10001);        System.out.println(user);        sqlSession.clearCache();        System.out.println("=========================================");        User user2 = userMapper.getUserById(10001);        System.out.println(user2);        sqlSession.close();    }

使用清除缓存的语句后,即便查询相同数据也需要再次查询数据库。

(本人仅作个人学习记录用,如有纰漏敬请指正)