It is recommended that the cache be placed in the service layer. You can customize your own BaseService Impl override annotation parent class method and inherit your own implementation. For convenience, we put the cache in the mapper layer. mybatis-plus integrates redis as a secondary cache, which is slightly different from mybatis integrates redis.
1. mybatis-plus opens the secondary cache
mybatis-plus.configuration.cache-enabled=true
2. Beans defining RedisTemplate are handed over to spring management, where some serialization operations are performed in order to directly access objects to redis
@Bean(value = "redisTemplate") public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>(); redisTemplate.setConnectionFactory(connectionFactory); //Use Jackson 2Json RedisSerializer to serialize and deserialize the value of redis (default JDK serialization) Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); //Serialize class names into json strings objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); //Ignore attributes that exist in JSON strings and are not actually present in Java objects when setting input objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); jackson2JsonRedisSerializer.setObjectMapper(objectMapper); //Use String RedisSerializer to serialize and deserialize the key value of redis RedisSerializer redisSerializer = new StringRedisSerializer(); //key redisTemplate.setKeySerializer(redisSerializer); redisTemplate.setHashKeySerializer(redisSerializer); //value redisTemplate.setValueSerializer(jackson2JsonRedisSerializer); redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer); redisTemplate.afterPropertiesSet(); return redisTemplate; }
3. Customize your own cache management
package com.qctchina.headsetserver.config; import com.qctchina.headsetserver.util.SpringUtil; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.cache.Cache; import org.springframework.data.redis.connection.RedisServerCommands; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.util.CollectionUtils; import java.util.Set; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * @author shuangyueliao * @create 2019/9/10 14:02 * @Version 0.1 */ @Slf4j public class MybatisRedisCache implements Cache { // Read write lock private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); //The redis cache is used here, and springboot is used for automatic injection. private RedisTemplate<String, Object> redisTemplate; private String id; public MybatisRedisCache(final String id) { if (id == null) { throw new IllegalArgumentException("Cache instances require an ID"); } this.id = id; } @Override public String getId() { return this.id; } @Override public void putObject(Object key, Object value) { if (redisTemplate == null) { //Because injection fails during startup, only injection during runtime can be done, and this code can be deleted. redisTemplate = (RedisTemplate<String, Object>) SpringUtil.getBean("redisTemplate"); } if (value != null) { redisTemplate.opsForValue().set(key.toString(), value); } } @Override public Object getObject(Object key) { if (redisTemplate == null) { //Because injection fails during startup, only injection during runtime can be done, and this code can be deleted. redisTemplate = (RedisTemplate<String, Object>) SpringUtil.getBean("redisTemplate"); } try { if (key != null) { return redisTemplate.opsForValue().get(key.toString()); } } catch (Exception e) { e.printStackTrace(); log.error("Cache error "); } return null; } @Override public Object removeObject(Object key) { if (redisTemplate == null) { //Because injection fails during startup, only injection during runtime can be done, and this code can be deleted. redisTemplate = (RedisTemplate<String, Object>) SpringUtil.getBean("redisTemplate"); } if (key != null) { redisTemplate.delete(key.toString()); } return null; } @Override public void clear() { log.debug("wipe cache"); if (redisTemplate == null) { redisTemplate = (RedisTemplate<String, Object>) SpringUtil.getBean("redisTemplate"); } Set<String> keys = redisTemplate.keys("*:" + this.id + "*"); if (!CollectionUtils.isEmpty(keys)) { redisTemplate.delete(keys); } } @Override public int getSize() { if (redisTemplate == null) { //Because injection fails during startup, only injection during runtime can be done, and this code can be deleted. redisTemplate = (RedisTemplate<String, Object>) SpringUtil.getBean("redisTemplate"); } Long size = redisTemplate.execute((RedisCallback<Long>) RedisServerCommands::dbSize); return size.intValue(); } @Override public ReadWriteLock getReadWriteLock() { return this.readWriteLock; } }
SpringUtil is a tool class for manually retrieving bean s
@Component public class SpringUtil implements ApplicationContextAware { private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SpringUtil.applicationContext = applicationContext; } public static Object getBean(String name){ return applicationContext.getBean(name); } public static <T> T getBean(String name, Class<T> clazz){ return applicationContext.getBean(name, clazz); } public static <T> T getBean(Class<T> clazz){ return applicationContext.getBean(clazz); } }
4. Add the annotation @CacheNamespace to the mapper
@CacheNamespace(implementation= MybatisRedisCache.class,eviction=MybatisRedisCache.class) public interface CommonMapper extends BaseMapper<Common> {