前言
本篇博客主要分享和梳理mybatis相关技术点
正文
Mybatis中的一级缓存和二级缓存:
一级缓存:
一级缓存作用域是SqlSession,缓存data为resultsets和auto-mappings的结果。
一级缓存默认开启,无法关闭。
一级缓存失效的四种情况:
- 不同的SqlSession对应不同的一级缓存。
- 同一个SqlSession但是查询条件不同,导致生成的SQL语句不同。
- 同一个SqlSession两次查询期间执行了任何一次增删改操作。
- 同一个SqlSession两次查询期间手工清空了一级缓存。
二级缓存:
二级缓存作用域是mapper,多个SqlSession共享。
二级缓存默认不开启,需要手动在mapper配置文件中配置<cache/>
来开启。
二级缓存失效的三种情况: - 不同的mapper对应不同的二级缓存。
- 同一个mapper两次查询期间执行了任何一次增删改操作。
- 手工清空二级缓存。
二级缓存与一级缓存同时使用时,会优先查二级缓存,若二级缓存中存在,则直接拿来用;若二级缓存中不存在,则会查一级缓存,若一级缓存存在则直接用,若一级缓存也不存在,则会发起数据库查询,并将结果添加到一级缓存和二级缓存中。
一级缓存的代码示例:
SqlSession session = sqlSessionFactory.openSession();
User user1 = session.selectOne("com.zhaocunwei.mapper.UserMapper.findById", 1);
User user2 = session.selectOne("com.zhaocunwei.mapper.UserMapper.findById", 1);
// 由于查询条件相同,会从一级缓存中直接获取结果,不会发起第二次数据库查询
二级缓存的代码示例:
// UserMapper.xml
<cache/> // 开启二级缓存
// 测试代码
SqlSession session1 = sqlSessionFactory.openSession();
User user1 = session1.selectOne("com.zhaocunwei.mapper.UserMapper.findById", 1);
SqlSession session2 = sqlSessionFactory.openSession();
User user2 = session2.selectOne("com.zhaocunwei.mapper.UserMapper.findById", 1);
// 由于开启了二级缓存,第二次查询会从二级缓存中获取结果,不会发起数据库查询
同时使用一级缓存和二级缓存的代码示例:
// UserMapper.xml
<cache/> // 开启二级缓存
SqlSession session1 = sqlSessionFactory.openSession();
User user1 = session1.selectOne("com.zhaocunwei.mapper.UserMapper.findById", 1);
// 同一个session,由于一级缓存存在,直接从一级缓存获取
User user2 = session1.selectOne("com.zhaocunwei.mapper.UserMapper.findById", 1);
// 新开一个session,由于二级缓存存在,从二级缓存获取
SqlSession session2 = sqlSessionFactory.openSession();
User user3 = session2.selectOne("com.zhaocunwei.mapper.UserMapper.findById", 1);
Springboot 使用缓存
在Spring Boot中使用Mybatis二级缓存的步骤:
- 在Mapper接口方法上使用@CacheNamespace注解开启二级缓存:
@CacheNamespace(blocking = true) public interface UserMapper { @Select("SELECT * FROM user WHERE id = #{id}") User findById(Integer id); }
- 在application.yml中配置二级缓存:
mybatis: configuration: cache-enabled: true # 开启全局二级缓存 mapper-locations: classpath*:mapper/*.xml
- 实现Cache接口并注册到Spring容器中:
@org.springframework.context.annotation.Configuration public class MybatisCacheConfig { @Bean public Cache getCache() { return new MybatisCache(); } private class MybatisCache implements Cache { private final Map<String, Object> cache = new ConcurrentHashMap<>(); @Override public String getId() { return getClass().getSimpleName(); } @Override public void putObject(Object key, Object value) { cache.put(key.toString(), value); } @Override public Object getObject(Object key) { return cache.get(key.toString()); } @Override public Object removeObject(Object key) { return cache.remove(key.toString()); } @Override public void clear() { cache.clear(); } @Override public int getSize() { return cache.size(); } } }
- 测试二级缓存:
@SpringBootTest class UserMapperTest { @Autowired private UserMapper userMapper; @Test void testCache() { User user1 = userMapper.findById(1); User user2 = userMapper.findById(1); assertSame(user1, user2); // 从二级缓存获取 } }
在Spring Boot项目中使用Mybatis时,有几点需要注意:
- Mapper扫描。需要使用@MapperScan注解指定Mapper接口的包,否则Spring Boot无法识别Mapper接口。
- 配置文件位置。Mybatis的配置文件mapper.xml的位置应在resources目录下,或使用@MapperScan指定basePackages后,该注解会自动查找该包及子包下的mapper.xml文件。
- 数据库配置。数据库连接信息配置在application.yml中,使用spring.datasource开头的配置项指定。
- PageHelper分页插件的使用。如果需要使用Mybatis的PageHelper分页插件,需要在主程序入口处添加@EnablePageHelper注解启用该插件。
- 配置文件优先级。application.yml > mapper.xml > 代码注解。相同的配置,以优先级高的为准。
- Cache缓存注解。@CacheNamespace开启Mapper级别缓存,@Cacheable等注解在方法上指定 caching 规则。需要配置mybatis.configuration.cacheEnabled=true开启全局Cache。
- 类型别名。使用@Alias注解配置实体类的类型别名,方便在xml和注解中使用。
- 映射文件位置。mappper接口名和mapper.xml文件应同名,且放在同一路径下。也可以在@MapperScan中指定mappers属性指定映射文件位置。
- 插件使用。想要使用第三方Mybatis插件,需要配置在mybatis-config.xml文件中。
- 分页插件的使用。PageHelper分页插件的使用依赖pagehelper-spring-boot-starter启动器,使用很简单,在查询方法上加@PageHelper注解即可。
mybatis的一级缓存和二级缓存