【MyBatis笔记11】Mybatis中的一级缓存和二级缓存

这篇文章,主要介绍MyBatis框架中的一级缓存和二级缓存。

目录

一、MyBatis一级缓存

1.1、一级缓存的使用

1.2、一级缓存失效情况

(1)不同的SqlSession会话查询

(2)同一个SqlSession查询条件不同

(3)同一个SqlSession两次查询之间有增删改操作

(4)同一个SqlSession两次查询之间有手动清空缓存

(5)同一个SqlSession不同的Mapper

二、MyBatis二级缓存

2.1、二级缓存的使用

(1)配置文件开启二级缓存

(2)XML映射文件启用二级缓存

(3)实体类必须实现序列化接口

(4)关闭或者提交SqlSession

2.2、二级缓存失效情况


一、MyBatis一级缓存

Mybatis框架是操作数据库的一种技术,为了考虑查询效率,Mybatis采用了两种缓存技术提高查询效率,分别是一级缓存和二级缓存。

MyBatis缓存,在第一次查询SQL的时候会从数据库里面进行查询,而从第二次开始,如果是相同的查询SQL语句,那么Mybatis框架不会从数据库里面查询,而是直接从MyBatis自己维护的缓存里面将数据返回,这就是MyBatis缓存的功能。一级缓存大致流程如下所示:

【MyBatis笔记11】Mybatis中的一级缓存和二级缓存_第1张图片

1.1、一级缓存的使用

MyBatis框架中,默认开启的就是【一级缓存】,一级缓存也叫做【本地缓存】,它的本质就是MyBatis自身维护了一个Map集合,查询时候先从Map集合里面查询,没有查询到则从数据库中进行查询,下面看下【一级缓存】的使用。

因为Mybatis默认是开启一级缓存的,所以我们不需要进行任何的配置,这里给通过一个案例来了解以下MyBatis一级缓存。

  • 使用MyBatis编写一个查询功能,然后连续两次调用相同的查询方法,查看控制台输入结果。

【MyBatis笔记11】Mybatis中的一级缓存和二级缓存_第2张图片

1.2、一级缓存失效情况

MyBatis框架中的一级缓存并不是万能的,它也有不起作用的时候,主要有下面几种情况会导致一级缓存失效。

(1)不同的SqlSession会话查询

当我们调用相同的查询方法,并且查询条件也是相同的时候,但是唯一不同的就是使用了不同的【SqlSession】会话连接,那么这种情况下,MyBatis的一级缓存就会失效了。

User user = new User();
user.setUsername("测试一级缓存");

// 第一次查询
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List query = userMapper.query(user);
System.out.println("第一次查询打印结果: ");
query.forEach(System.out::println);

// 相同SQL第二次查询
// 获取新的 SqlSession
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper userMapper2 = sqlSession2.getMapper(UserMapper.class);
query = userMapper2.query(user);
System.out.println("第二次查询打印结果: ");
query.forEach(System.out::println);

执行结果如下所示:

【MyBatis笔记11】Mybatis中的一级缓存和二级缓存_第3张图片

(2)同一个SqlSession查询条件不同

当我们调用相同的查询方法,但是传递的查询条件不同,那么这种情况下,MyBatis的一级缓存也会失效,想一想也知道,虽然你是相同的方法,但是你的查询条件都不一样了,那肯定缓存失效了。

// 执行操作
User user = new User();
user.setUsername("测试一级缓存");

// 第一次查询
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List query = userMapper.query(user);
System.out.println("第一次查询打印结果: ");
query.forEach(System.out::println);

// 相同SQL第二次查询
user.setUsername("测试一级缓存2");
// 获取新的 SqlSession
query = userMapper.query(user);
System.out.println("第二次查询打印结果: ");
query.forEach(System.out::println);

执行结果如下所示:

【MyBatis笔记11】Mybatis中的一级缓存和二级缓存_第4张图片

(3)同一个SqlSession两次查询之间有增删改操作

当调用相同的查询方法,但是在两次查询期间,我们有通过MyBatis框架执行增加、删除、修改等操作数据表,那么这个时候,MyBatis的一级缓存也会失效。这里失效的原因是MyBatis执行增加、删除、修改等操作的时候,MyBatis会将一级缓存清空。

// 执行操作
User user = new User();
user.setUsername("测试一级缓存");

// 第一次查询
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List query = userMapper.query(user);
System.out.println("第一次查询打印结果: ");
query.forEach(System.out::println);

// 新增一条数据
userMapper.remove("10007");

// 相同SQL第二次查询
// 获取新的 SqlSession
query = userMapper.query(user);
System.out.println("第二次查询打印结果: ");
query.forEach(System.out::println);

执行结果如下所示:

【MyBatis笔记11】Mybatis中的一级缓存和二级缓存_第5张图片

(4)同一个SqlSession两次查询之间有手动清空缓存

当我们再两次查询之间,手动调用【sqlSession.clearCache()】清空缓存的方法时候,这种情况也会导致一级缓存失效。

// 执行操作
User user = new User();
user.setUsername("测试一级缓存");

// 第一次查询
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List query = userMapper.query(user);
System.out.println("第一次查询打印结果: ");
query.forEach(System.out::println);

// 手动清空缓存
sqlSession.clearCache();

// 相同SQL第二次查询
// 获取新的 SqlSession
query = userMapper.query(user);
System.out.println("第二次查询打印结果: ");
query.forEach(System.out::println);

执行结果如下所示:

【MyBatis笔记11】Mybatis中的一级缓存和二级缓存_第6张图片

(5)同一个SqlSession不同的Mapper

当我们使用的是同一个SqlSession会话,但是查询的方法是在不同的Mapper映射文件里面,即使执行的SQL语句是相同,这种情况下,MyBatis的一级缓存同样会失效。

User user = new User();
user.setUsername("测试一级缓存");

// 第一次查询
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List query = userMapper.query(user);
System.out.println("第一次查询打印结果: ");
query.forEach(System.out::println);

// 相同SQL第二次查询
// 获取新的 SqlSession
UserMapper2 userMapper2 = sqlSession.getMapper(UserMapper2.class);
query = userMapper2.query(user);
System.out.println("第二次查询打印结果: ");
query.forEach(System.out::println);

执行结果如下所示:

【MyBatis笔记11】Mybatis中的一级缓存和二级缓存_第7张图片

以上就是MyBatis一级缓存以及几种失效的情况,MyBatis的一级缓存是SqlSession级别的,不同的SqlSession中执行相同的查询操作,不会触发缓存。

二、MyBatis二级缓存

由于MyBatis的一级缓存是基于SqlSession级别的,如果在不同的SqlSession里面执行相同的查询语句,就会导致缓存失效的情况,所以为了解决这些问题MyBatis提出了二级缓存的概念。二级缓存,它是基于SqlSessionFactory级别的,而SqlSessionFactory对象是唯一的,一个MyBatis工程中只会有一个SqlSessionFactory对象,这就相当于全局作用域。二级缓存大致流程如下所示:

【MyBatis笔记11】Mybatis中的一级缓存和二级缓存_第8张图片

二级缓存就能够解决了跨Mapper映射文件的缓存问题,要使用MyBatis的二级缓存,必须自己手动的开启二级缓存,下面介绍如何使用MyBatis的二级缓存。

2.1、二级缓存的使用

二级缓存的使用,需要满足下面四个条件:

  1. mybatif配置文件中通过【】标签开启二级缓存。
  2. 在XML映射文件中使用【】标签启用二级缓存。
  3. 二级缓存必须在【SqlSession】关闭或者提交之后有效。
  4. 二级缓存中的java实体类必须实现【Serializable】序列化接口。

(1)配置文件开启二级缓存

在【myabtis-config.xml】配置文件中,通过【】标签开启二级缓存。


    
    

(2)XML映射文件启用二级缓存

在需要使用二级缓存的XML映射文件里面,添加【】标签,这个标签的作用就是告诉MyBatis,当前这个XML映射文件中的所有查询方法的查询结果,都需要保存到二级缓存里面。




    
    

(3)实体类必须实现序列化接口

public class User implements Serializable {
    private Integer id;
    private String username;
    private String password;
}

(4)关闭或者提交SqlSession

// 第一次查询
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession1.getMapper(UserMapper.class);
List query = userMapper.query(user);
System.out.println("第一次查询打印结果: ");
query.forEach(System.out::println);
// 关闭 SqlSession
sqlSession1.close();

// 相同SQL第二次查询
// 获取新的 SqlSession
SqlSession sqlSession2 = sqlSessionFactory.openSession();
userMapper = sqlSession2.getMapper(UserMapper.class);
query = userMapper.query(user);
System.out.println("第二次查询打印结果: ");
query.forEach(System.out::println);
// 关闭 SqlSession
sqlSession2.close();

运行上面代码,查看控制台输出结果。

【MyBatis笔记11】Mybatis中的一级缓存和二级缓存_第9张图片

以上就是MyBatis二级缓存的使用。

2.2、二级缓存失效情况

MyBatis二级缓存也有失效的情况,那就是当有进行任何的增加、删除、修改等操作的时候,都将清空二级缓存,这个时候就会从数据库中查询。

// 第一次查询
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession1.getMapper(UserMapper.class);
List query = userMapper.query(user);
System.out.println("第一次查询打印结果: ");
query.forEach(System.out::println);
// 执行删除操作
userMapper.remove("10007");
// 关闭 SqlSession
sqlSession1.close();

// 相同SQL第二次查询
// 获取新的 SqlSession
SqlSession sqlSession2 = sqlSessionFactory.openSession();
userMapper = sqlSession2.getMapper(UserMapper.class);
query = userMapper.query(user);
System.out.println("第二次查询打印结果: ");
query.forEach(System.out::println);
// 关闭 SqlSession
sqlSession2.close();

上面代码就是在查询期间,有进行删除数据的操作,这个时候,二级缓存就会被清空,从而导致二级缓存失败。

【MyBatis笔记11】Mybatis中的一级缓存和二级缓存_第10张图片

以上,就是MyBatis框架中一级缓存和二级缓存的介绍。

综上,这篇文章结束了,主要介绍MyBatis框架中的一级缓存和二级缓存。

你可能感兴趣的:(SSM专栏,mybatis,缓存,一级缓存,二级缓存,缓存失效情况)