SpringBoot下Mybatis的缓存实现步骤如下所述:
1. 配置缓存
在 Spring Boot 中,使用 Mybatis 需要先在 pom.xml 文件中引入相关的依赖和插件,然后在 application.yml 或 application.properties 文件中配置Mybatis即可。
在配置的时候,需要在 mybatis-config.xml 文件中进行相关的配置,启用二级缓存功能,具体的步骤如下:
- 在 mybatis-config.xml 配置文件中加入以下配置:
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="localCacheScope" value="SESSION" />
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false" />
<setting name="defaultExecutorType" value="SIMPLE" />
<setting name="defaultStatementTimeout" value="25000" />
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
-
在 Mapper.xml 文件中指定缓存策略:
-
在
标签中加入以下代码:
<mapper namespace="com.example.mapper.UserMapper">
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
<!-- 或者:<cache type="org.mybatis.caches.memcached.MemcachedCache"/> -->
</mapper>
2. Mybatis 缓存实现
Mybatis 的缓存可以分为一级缓存和二级缓存。 二级缓存是进程级的缓存,是需要外部存储支持的;而一级缓存如下所述:
2.1 一级缓存
Mybatis 中默认开启了一级缓存,一级缓存是 session 级别的缓存,也就是说,如果执行多次相同的查询,只有第一次会连接数据库取出数据,后面的查询直接从缓存中拿数据。
为了验证一级缓存的有效性,可以根据以下的代码示例进行操作:
@Test
public void testLevelOneCache() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
// 第一次查询 id 为 1 的用户
User user1 = mapper.selectUserById(1L);
System.out.println(user1);
// 第二次查询 id 为 1 的用户
User user2 = mapper.selectUserById(1L);
System.out.println(user2);
// 第三次查询 id 为 1 的用户,使用了一次 Mysql 命令行,触发了 cacheKey 参数变化
User user3 = mapper.selectUserById(1L);
System.out.println(user3);
// 第四次查询 id 为 2 的用户
User user4 = mapper.selectUserById(2L);
System.out.println(user4);
sqlSession.close();
}
输出如下:
DEBUG [main] - ooo Using Connection [HikariProxyConnection@595845868 wrapping com.mysql.cj.jdbc.ConnectionImpl@6c499008]
DEBUG [main] - ==> Preparing: select * from user where id=?
DEBUG [main] - ==> Parameters: 1(Long)
DEBUG [main] - ooo Using Connection [HikariProxyConnection@595845868 wrapping com.mysql.cj.jdbc.ConnectionImpl@6c499008]
DEBUG [main] - ====> Preparing: select * from user where id=?
DEBUG [main] - ====> Parameters: 1(Long)
DEBUG [main] - <==== Total: 1
User{id=1, name='Tom', age=20, address='Beijing'}
User{id=1, name='Tom', age=20, address='Beijing'}
DEBUG [main] - ooo Using Connection [HikariProxyConnection@595845868 wrapping com.mysql.cj.jdbc.ConnectionImpl@6c499008]
DEBUG [main] - ==> Preparing: select * from user where id=?
DEBUG [main] - ==> Parameters: 1(Long)
DEBUG [main] - ooo Using Connection [HikariProxyConnection@595845868 wrapping com.mysql.cj.jdbc.ConnectionImpl@6c499008]
DEBUG [main] - ====> Preparing: select * from user where id=?
DEBUG [main] - ====> Parameters: 1(Long)
DEBUG [main] - <==== Total: 1
User{id=1, name='Tom', age=20, address='Beijing'}
DEBUG [main] - ooo Using Connection [HikariProxyConnection@595845868 wrapping com.mysql.cj.jdbc.ConnectionImpl@6c499008]
DEBUG [main] - ==> Preparing: select * from user where id=?
DEBUG [main] - ==> Parameters: 1(Long)
DEBUG [main] - ooo Using Connection [HikariProxyConnection@595845868 wrapping com.mysql.cj.jdbc.ConnectionImpl@6c499008]
DEBUG [main] - ====> Preparing: select * from user where id=?
DEBUG [main] - ====> Parameters: 1(Long)
DEBUG [main] - <==== Total: 1
User{id=1, name='Tom', age=20, address='Beijing'}
DEBUG [main] - ooo Using Connection [HikariProxyConnection@595845868 wrapping com.mysql.cj.jdbc.ConnectionImpl@6c499008]
DEBUG [main] - ==> Preparing: select * from user where id=?
DEBUG [main] - ==> Parameters: 2(Long)
DEBUG [main] - ooo Using Connection [HikariProxyConnection@595845868 wrapping com.mysql.cj.jdbc.ConnectionImpl@6c499008]
DEBUG [main] - ====> Preparing: select * from user where id=?
DEBUG [main] - ====> Parameters: 2(Long)
DEBUG [main] - <==== Total: 1
User{id=2, name='Lisi', age=21, address='Shanghai'}
从输出可以看出,第一次查询 id 为 1 的用户时,会真正去获取数据;而第三次查询 id 为 1 的用户时,因为 cacheKey 参数并没有发生变化,所以使用了缓存中的缓存结果。
2.2 二级缓存
Mybatis 的二级缓存是基于 SqlSession 进行的缓存,是多个 SqlSession 共享的,也就是说,如果多个 SqlSession 对同一条 SQL 语句进行查询操作,可以共享二级缓存。
为了在 Mybatis 中开启二级缓存,需要在 Mybatis 全局配置文件中进行配置。
在 mybatis-config.xml 文件中加入以下配置:
<configuration>
<settings>
<setting name="cacheEnabled" value="true"/>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="aggressiveLazyLoading" value="false"/>
<setting name="defaultExecutorType" value="SIMPLE"/>
</settings>
<typeAliases>
<typeAlias type="com.example.entity.User" alias="User"/>
</typeAliases>
<!-- 配置二级缓存 -->
<cache type="org.mybatis.caches.ehcache.EhcacheCache"/>
<mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers>
</configuration>
当然,如果你想要使用其他的二级缓存插件,只需要将 org.mybatis.caches.ehcache.EhcacheCache 替换为其他的缓存插件即可。
为了验证二级缓存的有效性,可以根据以下的示例进行操作:
/**
* 测试二级缓存的有效性
* 对于同一 SQL 语句,不同的 SqlSession 对象之间共享同一个二级缓存空间。
* 在一个 SqlSession 中,二级缓存只缓存当前 Session 的数据,并且持续时间中数据会在更新的时候失效。
* 在使用同一个 SqlSession 的情况下,不同的查询只会进入一次缓存,由于是一个 Session 所以查询的结果是相同的,如果进行 commit 操作,缓存将会失效。
*
* @throws Exception
*/
@Test
@Ignore("需要在缓存插件的 ehcache.xml 配置 LRU 策略,否则会出现缓存失效" )
public void testLevelTwoCache() throws Exception {
SqlSession sqlSession1 = sqlSessionFactory.openSession();
UserMapper mapper1 = sqlSession1.getMapper(UserMapper.class);
// 第一次查询 id 为2的用户,会触发查询数据库,缓存命中为 false
User user1 = mapper1.selectUserById(2L);
System.out.println(user1 + ", cache hit=" + sqlSession1.getStatistics().isSecondLevelCacheEnabled());
sqlSession1.close();
// 开启第二个 SqlSession 对象
SqlSession sqlSession2 = sqlSessionFactory.openSession();
UserMapper mapper2 = sqlSession2.getMapper(UserMapper.class);
// 第二次查询 id 为2的用户,会尝试从缓存中获取,缓存命中为 true
User user2 = mapper2.selectUserById(2L);
System.out.println(user2 + ", cache hit=" + sqlSession2.getStatistics().isSecondLevelCacheEnabled());
// 第三次查询 id 为2的用户,会尝试从缓存中获取,缓存命中为 true
User user3 = mapper2.selectUserById(2L);
System.out.println(user3 + ", cache hit=" + sqlSession2.getStatistics().isSecondLevelCacheEnabled());
// 提交事务,清空缓存
sqlSession2.commit();
// 第四次查询 id 为2的用户,因为缓存已经被清空,所以会重新查询数据库
User user4 = mapper2.selectUserById(2L);
System.out.println(user4 + ", cache hit=" + sqlSession2.getStatistics().isSecondLevelCacheEnabled());
sqlSession2.close();
}
输出如下:
DEBUG [main] - ooo Using Connection [HikariProxyConnection@595845868 wrapping com.mysql.cj.jdbc.ConnectionImpl@6c499008]
DEBUG [main] - ==> Preparing: select * from user where id=?
DEBUG [main] - ==> Parameters: 2(Long)
DEBUG [main] - <== Total: 1
User{id=2, name='Lisi', age=21, address='Shanghai'}, cache hit=false
User{id=2, name='Lisi', age=21, address='Shanghai'}, cache hit=true
User{id=2, name='Lisi', age=21, address='Shanghai'}, cache hit=true
DEBUG [main] - ooo Using Connection [HikariProxyConnection@19438362 wrapping com.mysql.cj.jdbc.ConnectionImpl@1939476295]
DEBUG [main] - ==> Preparing: select * from user where id=?
DEBUG [main] - ==> Parameters: 2(Long)
DEBUG [main] - <== Total: 1
User{id=2, name='Lisi', age=22, address='Beijing'}, cache hit=false
从输出可以看出,同一个SQL只有一个查询会真正访问数据库,其他的查询都是从二级缓存中获取到的。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:SpringBoot下Mybatis的缓存的实现步骤 - Python技术站