1. 程式人生 > 實用技巧 >Mybatis-plus使用redis做二級快取

Mybatis-plus使用redis做二級快取

建議快取放到 service 層,你可以自定義自己的 BaseServiceImpl 重寫註解父類方法,繼承自己的實現。為了方便,這裡我們將快取放到mapper層。mybatis-plus整合redis作為二級快取與mybatis整合redis略有不同。

1. mybatis-plus開啟二級快取

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    jdbc-url: jdbc:mysql://192.168.222.155:3306/sys?serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&characterEncoding=utf-8
username: root password: 123456 redis: host: 39.104.203.155 port: 6380 password: 123456 database: 1 timeout: 2000ms # 連線超時時間(毫秒)預設是2000ms lettuce: pool: max-active: 200 # 連線池最大連線數(使用負值表示沒有限制) max-wait: -1ms # 連線池最大阻塞等待時間(使用負值表示沒有限制) max-idle: 100 # 連線池中的最大空閒連線 min-idle: 50 # 連線池中的最小空閒連線 shutdown-timeout: 100ms # sentinel: # 哨兵模式 # master: mymaster # nodes: 192.168.222.155:26379,192.168.222.155:26380,192.168.222.155:26381


mybatis-plus:
mapper-locations: classpath*:/mapper/*.xml
type-aliases-package: com.redis.shaobing.entity
global-config:
db-config:
id-type: auto
table-underline: true
configuration:
cache-enabled: true
map-underscore-to-camel-case: true

2. 自定義自己的快取管理

package com.redis.shaobing.utils;


import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.databind.ObjectMapper; 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.data.redis.serializer.Jackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; 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 { // 讀寫鎖 private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(true); //這裡使用了redis快取,使用springboot自動注入 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; } public RedisTemplate<String, Object> getRedisTemplate() { redisTemplate = (RedisTemplate<String, Object>) ApplicationContextUtils.getBean("redisTemplate"); Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer(Object.class); ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); serializer.setObjectMapper(mapper); //使用StringRedisSerializer來序列化和反序列化redis的key值 redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(serializer); redisTemplate.setHashKeySerializer(new StringRedisSerializer()); redisTemplate.setHashValueSerializer(serializer); redisTemplate.afterPropertiesSet(); return redisTemplate; } @Override public String getId() { return this.id; } @Override public void putObject(Object key, Object value) { if (redisTemplate == null) { //由於啟動期間注入失敗,只能執行期間注入,這段程式碼可以刪除 redisTemplate = getRedisTemplate(); } if (value != null) { redisTemplate.opsForValue().set(key.toString(), value); } } @Override public Object getObject(Object key) { if (redisTemplate == null) { //由於啟動期間注入失敗,只能執行期間注入,這段程式碼可以刪除 redisTemplate = getRedisTemplate(); } try { if (key != null) { return redisTemplate.opsForValue().get(key.toString()); } } catch (Exception e) { e.printStackTrace(); log.error("快取出錯 "); } return null; } @Override public Object removeObject(Object key) { if (redisTemplate == null) { //由於啟動期間注入失敗,只能執行期間注入,這段程式碼可以刪除 redisTemplate = getRedisTemplate(); } if (key != null) { redisTemplate.delete(key.toString()); } return null; } @Override public void clear() { log.debug("清空快取"); if (redisTemplate == null) { redisTemplate = getRedisTemplate(); } Set<String> keys = redisTemplate.keys("*:" + this.id + "*"); if (!CollectionUtils.isEmpty(keys)) { redisTemplate.delete(keys); } } @Override public int getSize() { if (redisTemplate == null) { //由於啟動期間注入失敗,只能執行期間注入,這段程式碼可以刪除 redisTemplate = getRedisTemplate(); } Long size = redisTemplate.execute((RedisCallback<Long>) RedisServerCommands::dbSize); return size.intValue(); } @Override public ReadWriteLock getReadWriteLock() { return this.readWriteLock; } }

SpringUtil是手動獲取bean的工具類

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * 獲取java bean的工具
 */
@Component
public class ApplicationContextUtils implements ApplicationContextAware {

    private static ApplicationContext context;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

    /**
     *
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName) {
        return context.getBean(beanName);
    }
}

3. 在mapper上加上註解@CacheNamespace

@CacheNamespace(implementation= MybatisRedisCache.class,eviction=MybatisRedisCache.class)
@Mapper
public interface SysConfigDao extends BaseMapper<SysConfig> {}

如果呼叫該mapper下的方法,那麼會使用redis快取