当我们执行查询操作时,需要连接数据库,是一个十分耗资源的操作,如果我们将一次查询的结果放入缓存中,那么下一次再查该数据时就可以直接取缓存里面取,节省资源。
什么是缓存(cache)
①:存放在内存中的临时数据
②:我们将用户经常查询的数据放在缓存(内存)中,用户查询数据就不用再从磁盘上取,而是从缓存中取,可以提高查询效率,解决高并发系统的性能问题
为什么使用缓存
减少和数据库的交互次数,减少系统开销,提高系统效率
什么样的数据使用缓存
经常查询并且不经常改变的数据
MyBatis缓存MyBatis包含一个非常强大的查询缓存特性,它可以很方便地定制和配置缓存,缓存可以极大的提升查询效率
MyBatis 默认定义了两级缓存:一级缓存 和 二级缓存。默认情况下只有一级缓存开启(SqlSession 级别的缓存,也称为本地缓存)。二级缓存是 namespace 级别的缓存,需要手动开启和配置,我们可以使用 Cache 接口来自定义二级缓存。
一级缓存使用 User 表
我们在一次测试中来两次获取相同的用户
@Test public void test1(){ SqlSession sqlSession = MyBatisUtils.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = mapper.getUser(1); System.out.println(user); System.out.println("********************************"); User user1 = mapper.getUser(1); System.out.println(user1); sqlSession.close(); }
我们可以发现,只在第一次获取时使用 sql 查询了数据库,而在第二次查询时就没有使用 sql ,而是直接从缓存中取 user
一级缓存失效的情况:
①:查询不同的 user
②:增删改操作时,由于可能会改变原来的数据,因此一级缓存会失效
我们可以发现执行了两次 sql 语句,可以说明缓存失效
③:查询不同的 mapper.xml
④:手动清理缓存 sqlSession.clearCache()
同样执行了两次 sql
一级缓存默认是开启的,只在一个 sqlSession 中有效
二级缓存二级缓存也叫全局缓存,由于一级缓存的作用域太低了,所以产生了二级缓存,二级缓存在一个 namespace 中有效,一个名称空间对应一个二级缓存,不同的 mapper 查询出的数据会放在自己对应的缓存中,只有在 sqlSession 关闭后其中的一级缓存数据才会被存入二级缓存
步骤:
①:在核心配置文件中开启全局缓存
②:在对应 mapper.xml 文件中使用二级缓存
测试:使用两个不同的 sqlSession 来查询一个相同的 user
我们先关闭二级缓存
@Test public void test1(){ SqlSession sqlSession1 = MyBatisUtils.getSqlSession(); SqlSession sqlSession2 = MyBatisUtils.getSqlSession(); UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); User user1 = mapper1.getUser(1); System.out.println(user1); System.out.println("********************************"); User user2 = mapper2.getUser(1); System.out.println(user2); sqlSession1.close(); sqlSession2.close(); }
开启二级缓存
@Test public void test1(){ SqlSession sqlSession1 = MyBatisUtils.getSqlSession(); SqlSession sqlSession2 = MyBatisUtils.getSqlSession(); UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class); UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class); User user1 = mapper1.getUser(1); System.out.println(user1); sqlSession1.close(); System.out.println("********************************"); User user2 = mapper2.getUser(1); System.out.println(user2); sqlSession2.close(); }
注:二级缓存也可以使用以下方式开启,但是要将对应的数据序列化,否则会报错
序列化
缓存顺序
先查二级缓存中有没有,没有则去一级缓存中查,没有再去数据库中查询