一SpringBoot整合Redis实现Mybatis二级缓存
- 需要的maven依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.redis.demo</groupId>
<artifactId>springboot-mybatis</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-mybatis</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
<maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
- User实体类和UserMapper接口及UserMapper.xml配置文件
User实体类
public class User implements Serializable{
private static final long serialVersionUID = 1L;
private Integer id;
private String userName;
private String realName;
private Byte sex;
private String mobile;
private String email;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getRealName() {
return realName;
}
public void setRealName(String realName) {
this.realName = realName;
}
public Byte getSex() {
return sex;
}
public void setSex(Byte sex) {
this.sex = sex;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@Override
public String toString() {
return "User [id=" + id + ", userName=" + userName + ", realName=" + realName + ", sex=" + sex + ", mobile="
+ mobile + ", email=" + email + "]";
}
}
UserMapper接口
@Mapper
@CacheNamespace(implementation = MybatisRedisCache.class )
public interface UserMapper {
@Select("select * from user where id = #{id}")
User findById(Integer id);
User findById1(Integer id);
}
UserMapper.xml配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mybatis.lx.UserMapper">
<!-- <cache eviction="FIFO" readOnly="false" size="512" /> -->
<select id="findById1" resultType="com.spring.demo.entity.User" parameterType="java.lang.Integer">
select
*
from user
where id = #{id,jdbcType=INTEGER}
</select>
</mapper>
- mybatis-config.xml配置文件信息
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- MyBatis 配置 -->
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="lazyLoadingEnabled" value="false" />
<setting name="multipleResultSetsEnabled" value="" />
<setting name="useColumnLabel" value="true" />
<setting name="useGeneratedKeys" value="true" />
<setting name="autoMappingBehavior" value="FULL" />
<setting name="defaultExecutorType" value="REUSE" />
<setting name="defaultStatementTimeout" value="25" />
<setting name="safeRowBoundsEnabled" value="false" />
<setting name="localCacheScope" value="SESSION" />
<setting name="jdbcTypeForNull" value="OTHER" />
<setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString" />
<setting name="logImpl" value="SLF4J" />
<!-- 开启驼峰,开启后,只要数据库字段和对象属性名字母相同,无论中间加多少下划线都可以识别 -->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
<typeHandlers>
</typeHandlers>
</configuration>
- application.properties配置信息
#spring.datasource.username=root
#spring.datasource.password=y@888888
#spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#spring.datasource.hikari.jdbc-url==jdbc:mysql://127.0.0.1:3306/mybatis-test?characterEncoding=utf-8&serverTimezone=GMT&useSSL=false
spring.redis.password=lvnao888888
spring.redis.database=6
spring.redis.host=127.0.0.1
spring.redis.port=6379
#datasource config
spring.datasource.hikari.jdbc-url=jdbc:mysql://127.0.0.1:3306/mybatis-test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai
spring.datasource.hikari.username=root
spring.datasource.hikari.password=y@888888
spring.datasource.hikari.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.hikari.minimum-idle=3
spring.datasource.hikari.maximum-pool-size=15
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.max-lifetime=1800000
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.pool-name=HikariCP
mybatis.config-location=classpath:mybatis-config.xml
mybatis.type-aliases-package=
mybatis.mapper-locations=classpath:mappers/*.xml
- MybatisConfig配置类
@Configuration
@MapperScan(value= {"com.spring.demo"}, sqlSessionTemplateRef="sessionTemplate")
@EnableConfigurationProperties(MybatisProperties.class)
public class MybatisConfig extends MybatisAutoConfiguration{
public MybatisConfig(MybatisProperties properties, ObjectProvider<Interceptor[]> interceptorsProvider,
ObjectProvider<TypeHandler[]> typeHandlersProvider,
ObjectProvider<LanguageDriver[]> languageDriversProvider, ResourceLoader resourceLoader,
ObjectProvider<DatabaseIdProvider> databaseIdProvider,
ObjectProvider<List<ConfigurationCustomizer>> configurationCustomizersProvider) {
super(properties, interceptorsProvider, typeHandlersProvider, languageDriversProvider, resourceLoader,
databaseIdProvider, configurationCustomizersProvider);
}
@Bean(name = "dataSource")
@ConfigurationProperties(prefix = "spring.datasource.hikari")
@Primary
public DataSource createDataSouce() {
return org.springframework.boot.jdbc.DataSourceBuilder.create().build();
}
@Bean(name = "sqlSessionFactory")
@Override
public SqlSessionFactory sqlSessionFactory(@Qualifier("dataSource") DataSource dataSource) throws Exception {
return super.sqlSessionFactory(dataSource);
}
@Bean(name = "sessionTemplate")
@Primary
public SqlSessionTemplate createSqlSessionTemplate(@Qualifier("sqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
- Spring工具类,用于获取RedisTemplate,SpringContextUtils
/**
* spring上下文工具类
* @author Administrator
*
*/
@Component
@Slf4j
public class SpringContextUtils implements ApplicationContextAware, DisposableBean{
private static ApplicationContext applicationContext = null;
/**
* 取得存储在静态变量中的ApplicationContext.
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
SpringContextUtils.applicationContext = applicationContext;
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
@SuppressWarnings("unchecked")
public static <T> T getBean(String name) {
return (T) applicationContext.getBean(name);
}
/**
* 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型.
*/
public static <T> T getBean(Class<T> requiredType) {
return applicationContext.getBean(requiredType);
}
/**
* 清除SpringContextHolder中的ApplicationContext为Null.
*/
public static void clearHolder() {
if (log.isDebugEnabled()) {
log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext);
}
applicationContext = null;
}
/**
* 发布事件
*
* @param event
*/
public static void publishEvent(ApplicationEvent event) {
if (applicationContext == null) {
return;
}
applicationContext.publishEvent(event);
}
/**
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
*/
@Override
public void destroy() throws Exception {
SpringContextUtils.clearHolder();
}
}
- Redis实现mybatis二级缓存类
/**
* 开启mybatis二级缓存后,使用的缓存
* @author Administrator
*
*/
@Slf4j
public class MybatisRedisCache implements Cache{
private RedisTemplate<String, Object> redisTemplate = SpringContextUtils.getBean("redisTemplate");
private final String CACHE_KEY = "mybatis:cache:";
private String id;
public MybatisRedisCache(String id) {
super();
if(id == null) {
throw new IllegalArgumentException("缓存id不能为空");
}
this.id = id;
}
@Override
public String getId() {
return this.id;
}
@Override
public void putObject(Object key, Object value) {
log.info("存入mybatis二级缓存");
checkout(key);
redisTemplate.opsForValue().set(createKey(key), value);
}
@Override
public Object getObject(Object key) {
log.info("读取mybatis二级缓存信息");
checkout(key);
Object object = redisTemplate.opsForValue().get(createKey(key));;
return object;
}
@Override
public Object removeObject(Object key) {
checkout(key);
return redisTemplate.delete(createKey(key));
}
@Override
public void clear() {
redisTemplate.delete(this.CACHE_KEY);
}
@Override
public int getSize() {
return redisTemplate.getConnectionFactory().getConnection().dbSize().intValue();
}
public String createKey(Object key) {
return this.CACHE_KEY+ key.toString();
}
public void checkout(Object key) {
if(key == null) {
log.error("缓存key不能为空");
throw new IllegalArgumentException("缓存key不能为空");
}
}
}
- UserController测试类
@RestController
public class UserController {
@Autowired
private UserMapper userMapper;
@PostMapping("/findById")
public User findById(Integer id) {
return userMapper.findById(id);
}
}
9.测试结果