mybatis redis_微服务解决方案 MybatisPlus + Redis缓存,如何不太优雅的使用Redis缓存...

点击蓝色字07acfe609f686ef3b8912a57450c9371.png免费订阅,每天收到这样的好信息

前言:最近有不少粉丝关注本公众号。并且我已经成功开通了流量主同时会赚一点点广告费,我打算每个月把这部分钱拿出来给大家买点书刊,算是给大家一点福利吧。大家想买什么书扫描下方的加他拉你加群。最后,非常感谢大家的关注。

aa5822e24addd2e4dfd1319ea90d67c1.png

70510cea83eec522a6f449df60e94add.gif

如何不太优雅的使用Redis缓存

我们都知道使用redis来缓存我们的数据集合,如下图所示。0a834c1a8190fef851f0c64e0dde6dbf.png

通常自己去缓存数据,这样的优点就是逻辑清晰,而且rediskeyvalue会比较规范。但是冗余代码会比较多,需要自己进行判断数据是否过期。
为了简化业务代码,现在用注解的方式集成redis二级缓存,但是他的keyvalue就会比较不符合规范。他的key一共包含5个部分,最重要的就是sql和这个sql的参数。他的value就是这个查询的结果集。

准备工作

引入依赖,mybatis

<dependency>    <groupId>com.zaxxergroupId>    <artifactId>HikariCPartifactId>dependency><dependency>    <groupId>org.springframework.bootgroupId>    <artifactId>spring-boot-starter-jdbcartifactId>    <exclusions>                <exclusion>            <groupId>org.apache.tomcatgroupId>            <artifactId>tomcat-jdbcartifactId>        exclusion>    exclusions>dependency><dependency>    <groupId>com.baomidougroupId>    <artifactId>mybatis-plus-boot-starterartifactId>    <version>3.0.6version>dependency><dependency>    <groupId>com.baomidougroupId>    <artifactId>mybatis-plus-extensionartifactId>    <version>3.0.6version>dependency>

redis依赖

<dependency>    <groupId>org.springframework.bootgroupId>    <artifactId>spring-boot-starter-data-redisartifactId>dependency><dependency>    <groupId>org.apache.commonsgroupId>    <artifactId>commons-pool2artifactId>dependency>

配置文件

spring:  datasource:    type: com.zaxxer.hikari.HikariDataSource    driver-class-name: com.mysql.cj.jdbc.Driver    # 这里使用的是 ip:3336/db_order 的数据库(一个服务一个数据库)    url: jdbc:mysql://localhost:3306/sys-common?useUnicode=true&characterEncoding=utf-8&serverTimezone=Hongkong&useSSL=false    username: root    password: 123456    hikari:      minimum-idle: 5      idle-timeout: 600000      maximum-pool-size: 10      auto-commit: true      pool-name: MyHikariCP      max-lifetime: 1800000      connection-timeout: 30000      connection-test-query: SELECT 1  # redis  redis:    host: xxx.xxx.xxx.xxx    port: 6379    lettuce:      pool:        max-active: 8        max-idle: 8        max-wait: -1ms        min-idle: 0    database: 4

配置redisTemplate

import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.data.redis.serializer.StringRedisSerializer;/** * ProjectName:     hello-redis-cache * Package:         com.laoshiren.hello.redis.cache.mybatis.configure * ClassName:       RedisConfiguration * Author:          laoshiren * Description: * Date:            2020/9/13 15:49 * Version:         1.0 */@Configurationpublic class RedisConfiguration {    /**     * 设置redisTemplate     */    @Bean(name = "redisTemplate")    public RedisTemplate redisTemplate(LettuceConnectionFactory redisConnectionFactory) {        RedisTemplate redisTemplate = new RedisTemplate<>();        redisTemplate.setConnectionFactory(redisConnectionFactory);        // 使用String 序列化//        redisTemplate.setDefaultSerializer(new StringRedisSerializer());//        redisTemplate.setKeySerializer(new StringRedisSerializer());//        redisTemplate.setValueSerializer(new StringRedisSerializer());        redisTemplate.afterPropertiesSet();        return redisTemplate;    }}

注意这里我不使用String的序列化方式去序列化KeyValue

实现

实现Cache接口

package com.laoshiren.hello.redis.cache.mybatis.cache;import com.laoshiren.hello.redis.cache.mybatis.configure.ApplicationContextHolder;import lombok.extern.slf4j.Slf4j;import org.apache.ibatis.cache.Cache;import org.springframework.data.redis.core.RedisCallback;import org.springframework.data.redis.core.RedisTemplate;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.ReadWriteLock;import java.util.concurrent.locks.ReentrantReadWriteLock;/** * ProjectName:     hello-redis-cache * Package:         com.laoshiren.hello.redis.cache.mybatis.cache * ClassName:       RedisCache * Author:          laoshiren * Description: * Date:            2020/9/13 15:34 * Version:         1.0 */@Slf4jpublic class RedisCache implements Cache {    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();    private final 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;    }    /**     * Put query result to redis     *     * @param key     * @param value     */    @Override    public void putObject(Object key, Object value) {        try {            RedisTemplate redisTemplate = getRedisTemplate();            redisTemplate.opsForValue().set(key, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);            log.debug("Put query result to redis");        } catch (Throwable t) {            log.error("Redis put failed", t);        }    }    /**     * Get cached query result from redis     *     * @param key     * @return     */    @Override    public Object getObject(Object key) {        try {            RedisTemplate redisTemplate = getRedisTemplate();            log.info("Get cached query result from redis");//            System.out.println("****" + opsForValue.get(key).toString());            return redisTemplate.opsForValue().get(key);        } catch (Throwable t) {            log.error("Redis get failed, fail over to db", t);            return null;        }    }    /**     * Remove cached query result from redis     *     * @param key     * @return     */    @Override    @SuppressWarnings("unchecked")    public Object removeObject(Object key) {        try {            RedisTemplate redisTemplate = getRedisTemplate();            redisTemplate.delete( key.toString());            log.debug("Remove cached query result from redis");        } catch (Throwable t) {            log.error("Redis remove failed", t);        }        return null;    }    /**     * Clears this cache instance     */    @Override    public void clear() {        RedisTemplate redisTemplate = getRedisTemplate();        redisTemplate.execute((RedisCallback) connection -> {            connection.flushDb();            return null;        });        log.debug("Clear all the cached query result from redis");    }    /**     * This method is not used     *     * @return     */    @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配置缓存

@CacheNamespace(implementation = RedisCache.class)public interface TbPostMapper extends BaseMapper<TbPost> {}

测试

请求一次数据库,使用Debug模式,它的key是一个CacheKey,无法使用使用StringRedisSerializer去序列化,所以redisTemplate 得使用默认的序列化,即 JdkSerializationRedisSerializer

a00a1ee189c17ad7adafb3aaa4114658.png

打开RDM,看一下4号库。

cbfce7e008fda049e2e2cdf54b3e15d0.png

发现keyvalue就不是很美观,不过不影响使用,当然您可以使用StringRedisSerializer去实现,只不过我在尝试的过程中获取sql和参数的时候,会出现一点问题。希望有大佬可以指出。

带参数的sql

4140f729a2c4a43fa1ef431d75a972ad.png

特别注意! 在分页缓存的时候,Page对象的total必须自己手动查询一次,不然返回给前端的对象里第一次还有总页数,第二次由于走了缓存就不带这个total,所以必须手动查询一次。

@GetMapping("page/{pageNo}/{pageSize}")public ResponseResult> page(@PathVariable(name = "pageNo")Integer pageNo,                                        @PathVariable(name = "pageSize") Integer pageSize,                                        HttpServletRequest request){    IPage wherePage = new Page<>(pageNo, pageSize);    String word = request.getParameter("wd");    LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();    if (StringUtils.isNotBlank(word)) {        queryWrapper.like(Area::getAreaName,word);    }    int count = areaService.count(queryWrapper);    IPage page = areaService.page(wherePage,queryWrapper);    page.setTotal((long)count);    return new ResponseResult<>(CodeStatus.OK,"操作成功",page);}

好了,最后还是借用大佬的一句话:“不经一番寒彻骨,怎知梅花扑鼻香”。

435bf6cd4643520d08a82b7d2db0eb77.png 打油诗 我不在乎我的作品文章是被现在的人读还是由子孙后代来读。既然上帝花了六千年来等一位观察者,我可以花上一个世纪来等待读者。 7557f7fb75b811fc2592ed7baf56549a.png 

永久激活方案~

2020-07-29

81402fb3f7b74c3695164f4899114815.png

spring 状态机

2020-05-12

357db85bcef91145b0367e5de2ae9e15.png

mybatis用到的设计模式

2020-07-02

03eabee4fa90a1fe3c92a32000c1f068.png

jvm高级面试题(必须看)

2020-07-23

64341af79ef07e9b9323682715388b2c.png

MySQL索引实现原理分析

2020-05-19

fecea454fddbe34efaff7254484740ff.png

Spring中的用到的设计模式

2020-04-23

1d171feac4bc403e3fdc6b0634fad946.png

Spring 和 SpringBoot 之间到底有啥区别?

2020-05-29

c64a8c7adfd964de0ac22eec07651288.png

如何快速搭建一个免费的 鉴黄 平台

2020-08-15

66c60a7f95a93e3faaff92ff85c64995.png

美国也就那么回事吧

2020-08-15

36fae0224dfee549a433fc044681015b.png

5T的Java视频教程全部免费获取

2020-08-14

03f768d59907b9cffbfafa84ec70226c.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值