MyBatis入门(十)

180 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第11天,点击查看活动详情

MyBatis的缓存

MyBatis的一级缓存

  • 一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问
  • 使一级缓存失效的四种情况:
  1. 不同的SqlSession对应不同的一级缓存
  2. 同一个SqlSession但是查询条件不同
  3. 同一个SqlSession两次查询期间执行了任何一次增删改操作
  4. 同一个SqlSession两次查询期间手动清空了缓存
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
cacheMapper mapper = sqlSession.getMapper(cacheMapper.class);
Emp empByEid = mapper.getEmpByEid(1);
System.out.println(empByEid);
//        mapper.insert(new Emp(null,"张三",23,"男","123@qq.com"));缓存失效
//        sqlSession.clearCache();缓存失效
SqlSession sqlSession1 = SqlSessionUtils.getSqlSession();
cacheMapper mapper1 = sqlSession1.getMapper(cacheMapper.class);
Emp empByEid1 = mapper1.getEmpByEid(1);
System.out.println(empByEid1);
/**
 * 可以看到只执行过一次sql,第二次的数据是通过缓存获取的,这是一级缓存得到的,默认开启的,级别是SqlSession的
 * 在同一个SqlSession下查到的,都是缓存的,和mapper无关
 * DEBUG   Preparing: select * from t_emp where eid = ? (BaseJdbcLogger.java:137)
 * DEBUG Parameters: 1(Integer) (BaseJdbcLogger.java:137)
 * DEBUG 03-21 15:24:15,159 <==      Total: 1 (BaseJdbcLogger.java:137)
 * Emp{eid=1, empName='张三', age=12, sex='男', email='123@qq.com', dept=null}
 * Emp{eid=1, empName='张三', age=12, sex='男', email='123@qq.com', dept=null}
 *SqlSession sqlSession = SqlSessionUtils.getSqlSession();
 *         cacheMapper mapper = sqlSession.getMapper(cacheMapper.class);
 *         Emp empByEid = mapper.getEmpByEid(1);
 *         System.out.println(empByEid);
 *         SqlSession sqlSession1 = SqlSessionUtils.getSqlSession();
 *         cacheMapper mapper1 = sqlSession1.getMapper(cacheMapper.class);
 *         Emp empByEid1 = mapper1.getEmpByEid(1);
 *         System.out.println(empByEid1);
 * 这种是执行两次sql语句的,因为是获取了重新的SqlSession
 */

MyBatis的二级缓存

二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被 缓存;此后若再次执行相同的查询语句,结果就会从缓存中获取

二级缓存开启的条件

a>在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置

b>在映射文件中设置标签

c>二级缓存必须在SqlSession关闭或提交之后有效

d>查询的数据所转换的实体类类型必须实现序列化的接口

使二级缓存失效的情况

两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

b>在映射文件中设置标签
<cache/>
<!--    Emp getEmpByEid(@Param("eid") Integer eid );-->
    <select id="getEmpByEid" resultType="Emp">
        select * from t_emp where eid = #{eid}
    </select>
d>查询的数据所转换的实体类类型必须实现序列化的接口
public class Emp implements Serializable {
public void testCacheTwo(){
    try {
        InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
        SqlSessionFactory   sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
        SqlSession sqlSession1 = sqlSessionFactory.openSession(true);
        cacheMapper mapper = sqlSession1.getMapper(cacheMapper.class);
        System.out.println(mapper.getEmpByEid(1));
        sqlSession1.close();
        SqlSession sqlSession2 = sqlSessionFactory.openSession(true);
        cacheMapper mapper1 = sqlSession2.getMapper(cacheMapper.class);
        System.out.println(mapper1.getEmpByEid(1));
        sqlSession2.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
运行结果:
DEBUG 03-21 16:19:16,807 Cache Hit Ratio [com.aitiguigu.mybatis.mapper.cacheMapper]: 0.0 (LoggingCache.java:60) 
DEBUG 03-21 16:19:16,996 ==>  Preparing: select * from t_emp where eid = ? (BaseJdbcLogger.java:137) 
DEBUG 03-21 16:19:17,031 ==> Parameters: 1(Integer) (BaseJdbcLogger.java:137) 
DEBUG 03-21 16:19:17,059 <==      Total: 1 (BaseJdbcLogger.java:137) 
Emp{eid=1, empName='张三', age=12, sex='男', email='123@qq.com', dept=null}
WARN  03-21 16:19:17,097 As you are using functionality that deserializes object streams, it is recommended to define the JEP-290 serial filter. Please refer to https://docs.oracle.com/pls/topic/lookup?ctx=javase15&id=GUID-8296D8E8-2B93-4B9A-856E-0A65AF9B8C66 (SerialFilterChecker.java:46) 
DEBUG 03-21 16:19:17,100 Cache Hit Ratio [com.aitiguigu.mybatis.mapper.cacheMapper]: 0.5 (LoggingCache.java:60) 
Emp{eid=1, empName='张三', age=12, sex='男', email='123@qq.com', dept=null}