Springboot + Mybatis + Redis+mysql
Mybatis的二级缓存是多个SqlSession共享的,作用于是mapper配置文件中同一个namespace,不同的SqlSession两次执行相同namespace下的sql语句且参数如果也一样则最终执行的sql语句是相同的。每次查询都会先看看缓存中是否有对应查询结果,如果有就从缓存拿,如果没有就执行sql语句从数据库中读取,从而提高查询效率。
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 http://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.1.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.domcj.seccache</groupId>
<artifactId>secache</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>secache</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.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.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.7</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
#配置mybatis
mybatis:
mapper-locations: mapper/UserMapper.xml
type-aliases-package: com.domcj.seccache.seccache.entity
#配置redis
spring:
datasource:
url: jdbc:mysql://localhost:3306/chenjian
username: root
password: chenjian
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
redis:
host: localhost
port: 6379
database: 0
password:
SpringContextHolder
组件,实现了Spring的ApplicationContextAware来获取ApplicationContext,从中获取容器的bean
package com.domcj.seccache.seccache.util;
import java.util.Map;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
/**
* @description: This is a class!
* @author: chenjian
* @date: 2019/03/07 11:33
*/
@Component
public class ApplicationContextHolder implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
ApplicationContextHolder.applicationContext = applicationContext;
}
public ApplicationContext getApplicationContext() {
return applicationContext;
}
@SuppressWarnings("unchecked")
public static <T> T getBean(String beanName) {
checkApplicationContext();
return (T) applicationContext.getBean(beanName);
}
@SuppressWarnings("unchecked")
public static <T> Map<String, T> getBean(Class<T> clazz) {
checkApplicationContext();
return applicationContext.getBeansOfType(clazz);
}
private static void checkApplicationContext() {
if (applicationContext == null) {
throw new IllegalStateException("applicaitonContext未注入,请在applicationContext.xml中定义SpringContextHolder");
}
}
}
RedisCache Mybatis二级缓存默认使用的是其他的缓存,这里我们需要集成Redis就需要自己自定义写一个缓存类去实现二级缓存。
自定义缓存需要实现Mybatis的Cache接口。
package com.domcj.seccache.seccache.util;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
/**
* @description: This is a class!
* @author: chenjian
* @date: 2019/03/07 11:45
*/
public class RedisCache implements Cache {
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private String id; // cache instance id
private RedisTemplate redisTemplate;
private static final long EXPIRE_TIME_IN_MINUTES = 30; // redis过期时间
public RedisCache(String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
}
@Override
public String getId() {
return id;
}
@Override
public void putObject(Object key, Object value) {
RedisTemplate redisTemplate = getRedisTemplate();
ValueOperations opsForValue = redisTemplate.opsForValue();
opsForValue.set(key, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.SECONDS);
}
@Override
public Object getObject(Object key) {
RedisTemplate redisTemplate = getRedisTemplate();
ValueOperations opsForValue = redisTemplate.opsForValue();
Object obj = opsForValue.get(key);
return obj;
}
@Override
public Object removeObject(Object key) {
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.delete(key);
return null;
}
@Override
public void clear() {
RedisTemplate redisTemplate = getRedisTemplate();
redisTemplate.execute((RedisCallback) connection -> {
connection.flushDb();
return null;
});
}
@Override
public int getSize() {
return 0;
}
@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}
private RedisTemplate getRedisTemplate() {
if (redisTemplate == null) {
redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
}
return redisTemplate;
}
}
Mapper.xml
mapper映射配置文件,只需要引入刚刚配置好的自定义缓存类。
<?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.domcj.seccache.seccache.mapper.UserMapper">
<cache type="com.domcj.seccache.seccache.util.RedisCache">
<property name="eviction" value="LRU" />
<property name="flushInterval" value="600000" />
<property name="size" value="1024" />
<property name="readOnly" value="false" />
</cache>
<select id="getUserById" parameterType="java.lang.Long" resultType="User">
select * from user where id=#{id, jdbcType=BIGINT}
</select>
</mapper>
eviction:定义缓存移除机制(算法),默认为LRU(最近最少使用),它会清除最少使用的数据,还有一种FIFO(先进先出),它会清除最先进来的数据。
flushInterval:定义缓存刷新周期,单位为毫秒。
size:标识缓存cache中容纳的最大元素,默认为1024。
readOnly:默认为false,可配置为true缓存只读。
实体类
实体类需要实现Serializable
package com.domcj.seccache.seccache.entity; import java.io.Serializable; /** * @description: This is a class! * @author: chenjian * @date: 2019/03/07 11:21 */ public class User implements Serializable { private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
本文介绍如何在SpringBoot项目中整合Mybatis和Redis实现二级缓存,通过自定义RedisCache类实现Mybatis的Cache接口,提高数据查询效率。
6708

被折叠的 条评论
为什么被折叠?



