Mybatis Cache(二)MybatisCache+Redis

前面提到了,使用mybatis cache,一般是结合redis使用。

一、demo

1、数据表
create table demo.t_address
(
    id           int auto_increment
        primary key,
    address_name varchar(200) null,
    address_code varchar(20)  null,
    address_type int          null
);

项目结构:

2、pom
<?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>

    <groupId>org.example</groupId>
    <artifactId>plus-mybatis-cache</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.2.4</version>
        <relativePath/>
    </parent>


    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--尽量不要同时导入mybatis 和 mybatis_plus,避免版本差异-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-spring-boot3-starter</artifactId>
            <version>3.5.5</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.13</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
    </dependencies>
</project>
3、配置文件
server.port=1112
server.servlet.context-path=/mybatisCacheDemo
#mysql
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3308/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false
spring.datasource.username=root
spring.datasource.password=wtyy
#mybatis
mybatis.mapper-locations=classpath*:mapper/*Mapper.xml
#打印日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 开启二级缓存
mybatis-plus.configuration.cache-enabled=true
#redis
spring.data.redis.host=127.0.0.1
spring.data.redis.port=6379
spring.data.redis.password=
spring.data.redis.lettuce.pool.max-active=8
spring.data.redis.lettuce.pool.max-wait=-1
spring.data.redis.lettuce.pool.max-idle=8
spring.data.redis.lettuce.pool.min-idle=0
spring.data.redis.lettuce.pool.enabled=true
spring.data.redis.lettuce.pool.time-between-eviction-runs=30s
4、util
package com.pluscache.demo.util;

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

import java.lang.annotation.Annotation;
import java.util.Map;

@Component
public class ApplicationContextUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext ;

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

    public static Object getBean(String name) {
        return ApplicationContextUtil.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);
    }

    public static <T> Map<String, T> getBeansOfType(Class<T> clazz) {
        return applicationContext.getBeansOfType(clazz);
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public static <T extends Annotation> T getAnnotation(Object bean, Class<T> annotationClass) {
        T annotation = bean.getClass().getAnnotation(annotationClass);
        if (annotation == null) {
            annotation = AopUtils.getTargetClass(bean).getAnnotation(annotationClass);
        }
        return annotation;
    }

}
5、config
package com.pluscache.demo.config;

import com.pluscache.demo.util.ApplicationContextUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;

@Slf4j
//@Component
public class MybatisRedisCache implements Cache {

    /* * id是必须的带上的,这里的id会指定当前放入缓存的mapper的namespace
    * 如这里的id就是com.sample.dao.IEmployeeDao
    */
    private final String id;
    private  RedisTemplate redisTemplate;

    public MybatisRedisCache(final String id) {
       //获取redis实例
        //redisTemplate = (RedisTemplate) ApplicationContextUtil.getBean("redisTemplate");
        //指定key的序列化方式
        //redisTemplate.setKeySerializer(new StringRedisSerializer());
        //redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        this.id = id;
    }
    @Override
    public String getId() {
        return id;
    }

    @Override
    public void putObject(Object key, Object value) {
        this.getRedisTemplate();
        redisTemplate.opsForHash().put(id.toString(),key.toString(),value);
    }

    private void getRedisTemplate() {
        if (redisTemplate == null) {
            //由于启动期间注入失败,只能运行期间注入,这段代码可以删除
            redisTemplate = (RedisTemplate) ApplicationContextUtil.getBean("redisTemplate");
        }
    }

    @Override
    public Object getObject(Object key) {
        this.getRedisTemplate();
        return redisTemplate.opsForHash().get(id.toString(),key.toString());
    }

    @Override
    public Object removeObject(Object key) {
        return null;
    }

    @Override
    public void clear() {
        this.getRedisTemplate();
        redisTemplate.delete(id.toString());
    }

    @Override
    public int getSize() {
        this.getRedisTemplate();
        return redisTemplate.opsForHash().size(id.toString()).intValue();
    }
}
6、dto
package com.pluscache.demo.dto;

import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

@Data
@TableName("t_address")
public class AddressDTO implements Serializable {
    private Integer id;
    private String addressName;
    private String addressCode;
    public Integer addressType;
}
7、dao
(1)repository

   可以省略,移到service中

package com.pluscache.demo.repository;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.pluscache.demo.dto.AddressDTO;
import com.pluscache.demo.mapper.AddressMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
@Slf4j
public class AddressRepository {

    @Autowired
    private AddressMapper addressMapper;

    //plus新增
    public void insert(AddressDTO addressDTO) {
        addressMapper.insert(addressDTO);
    }

    //手动SQL新增
    public void save(AddressDTO addressDTO) {
        addressMapper.save(addressDTO);
    }

    public AddressDTO getById(Integer id) {
        LambdaQueryWrapper<AddressDTO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AddressDTO::getId, id);
        return addressMapper.selectOne(queryWrapper);
    }

    public List<AddressDTO> listByType(Integer type) {
        LambdaQueryWrapper<AddressDTO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AddressDTO::getAddressType, type);
        return addressMapper.selectList(queryWrapper);
    }

    public List<AddressDTO> listByTypeRecord(Integer type) {
        return addressMapper.listByTypeRecord(type);
    }

    public List<AddressDTO> listById(Integer id) {
        LambdaQueryWrapper<AddressDTO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AddressDTO::getId, id);
        return addressMapper.selectList(queryWrapper);
    }
}
(2)mapper

   在这里做的缓存

package com.pluscache.demo.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.pluscache.demo.config.MybatisRedisCache;
import com.pluscache.demo.dto.AddressDTO;
import org.apache.ibatis.annotations.CacheNamespace;
import org.apache.ibatis.annotations.Param;

import java.util.List;

@CacheNamespace(implementation = MybatisRedisCache.class, eviction = MybatisRedisCache.class)
public interface AddressMapper extends BaseMapper<AddressDTO> {

    void save(@Param("record") AddressDTO addressDTO);

    List<AddressDTO> listByTypeRecord(@Param("type") Integer type);
}
(3)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.pluscache.demo.mapper.AddressMapper">

    <cache-ref namespace="com.pluscache.demo.mapper.AddressMapper"/>

    <insert id="save">
        insert into t_address(address_name,
                              address_code,
                              address_type
                              ) values (#{record.addressName},
                                        #{record.addressCode},
                                        #{record.addressType})
    </insert>

    <select id="listByTypeRecord" resultType="com.pluscache.demo.dto.AddressDTO">
        select address_name,address_code from t_address where address_type =#{type}
    </select>

</mapper>
8、service
package com.pluscache.demo.service.impl;

import com.pluscache.demo.dto.AddressDTO;
import com.pluscache.demo.repository.AddressRepository;
import com.pluscache.demo.service.AddressService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service("addressService")
public class AddressServiceImpl implements AddressService {

    @Autowired
    private AddressRepository addressRepository;

    @Override
    public void insert(AddressDTO addressDTO) {
        addressRepository.insert(addressDTO);
    }

    @Override
    public void save(AddressDTO addressDTO) {
        addressRepository.save(addressDTO);
    }

    @Override
    public AddressDTO getById(Integer id) {
        return addressRepository.getById(id);
    }

    @Override
    public List<AddressDTO> listByType(Integer type) {
        return addressRepository.listByType(type);
    }

    @Override
    public List<AddressDTO> listByTypeRecord(Integer type) {
        return addressRepository.listByTypeRecord(type);
    }

    @Override
    public List<AddressDTO> listById(Integer id) {
        return addressRepository.listById(id);
    }
}
9、controller
package com.pluscache.demo.controller;

import com.pluscache.demo.dto.AddressDTO;
import com.pluscache.demo.service.AddressService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("/address")
public class AddressController {

    @Autowired
    private AddressService addressService;

    @RequestMapping("/insert")
    public void insert(AddressDTO addressDTO) {
        addressService.insert(addressDTO);
    }

    @RequestMapping("/save")
    public void save(AddressDTO addressDTO) {
        addressService.save(addressDTO);
    }

    @RequestMapping("/getById")
    public AddressDTO getById(Integer id) {
        return addressService.getById(id);
    }


    @RequestMapping("/listByType")
    public List<AddressDTO> listByType(Integer type) {
        return addressService.listByType(type);
    }

    @RequestMapping("/listByTypeRecord")
    public List<AddressDTO> listByTypeRecord(Integer type) {
        return addressService.listByTypeRecord(type);
    }


    @RequestMapping("/listById")
    public List<AddressDTO> listById(Integer id) {
        return addressService.listById(id);
    }

}
10、启动类
package com.pluscache.demo;


import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.pluscache.demo.mapper")
@SpringBootApplication
public class MybatisPlusApplication {

    public static void main(String[] args) {
        SpringApplication.run(MybatisPlusApplication.class, args);

    }
}
11、测试 
(1)新增数据

    新增了几条数据

(2)SQL法根据type查询

① 第一次访问

localhost:1112/mybatisCacheDemo/address/listByTypeRecord?type=1

后台打印:

查看redis生成了缓存

 ② 再次访问,没有查询db了

(3) mybatis-plus根据type查询

  ①  第一次访问localhost:1112/mybatisCacheDemo/address/listByType?type=1

后台从db查询

查看redis的缓存:可以看到又生成了一条缓存

②  再次访问,没有从数据库查询

 (4)mybatis-plus根据id查询

①  第一次访问localhost:1112/mybatisCacheDemo/address/listById?id=1

走db查看

查看redis缓存:

 ②  再次访问,不再走db查询

 (5)执行add

这里生成的id是自增长的,理论上,只需要清空type=1的缓存,不需要清空id=1的缓存。但是刷新redis可以看到,整个大key都清除了。

二、缺点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/640544.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Star CCM+在电池热管理中SOC计算、充电Map调用、电池内阻调用的方法

前言 众所周知电池充电电流是随着电池温度与容量变化查表获得(形式见下表),其中电池的充电倍率(电流)是阶梯变化的,而内阻是线型变化的。因此为了仿真的准确定,需要在软件中实现数据的调用,计算电池的发热量。 电池内阻/充电倍率表 一 SOC计算 SOC的估算方法有开路电…

selenium安装出错

selenium安装步骤&#xff08;法1&#xff09;&#xff1a; 安装失败法1 第一次实验&#xff0c;失败 又试了一次&#xff0c;失败 安装法2-失败&#xff1a; ERROR: Could not install packages due to an EnvironmentError: [WinError 5] 拒绝访问。: c:\\programdata\\a…

swust oj 1075: 求最小生成树(Prim算法)

#include <iostream> using namespace std;typedef struct {int n;int e;char data[500];int edge[500][500]; }Graph;typedef struct {int index;int cost; }mincost;typedef struct {int x;//起点int y;//终点int weight;//权重 }EDGE;typedef struct {int index;int …

Bugku Crypto 部分题目简单题解(四)

目录 python_jail 简单的rsa 托马斯.杰斐逊 这不是md5 进制转换 affine Crack it rsa python_jail 启动场景 使用虚拟机nc进行连接 输入print(flag) 发现报错&#xff0c;经过测试只能传入10个字符多了就会报错 利用python中help()函数&#xff0c;借报错信息带出flag变…

2024年商业管理与文化传播国际学术会议(ICBMCC 2024)

2024年商业管理与文化传播国际学术会议&#xff08;ICBMCC 2024) 2024 International Conference on Business Management and Cultural Communication 一、【会议简介】 2024年商业管理与文化传播国际学术会议&#xff08;ICBMCC 2024&#xff09;是一次汇集全球商业管理领域…

SwiftUI中的手势(MagnificationGesture、 RotationGesture)

通过前两篇文章的探索&#xff0c;手势的基本使用规则已经较深的了解&#xff0c;本篇文章主要看看放缩手势MagnificationGesture和旋转手势RotationGesture。 MagnificationGesture 放缩手势 放缩手势在App中用的也比较广泛&#xff0c;下面先看一个示例效果&#xff1a; 上…

必示科技参与智能运维国家标准预研线下编写会议并做主题分享

近日&#xff0c;《信息技术服务 智能运维 第3部分&#xff1a;算法治理》&#xff08;拟定名&#xff09;国家标准预研阶段第一次编写工作会议在杭州举行。本次会议由浙商证券承办。 此次编写有来自银行、证券、保险、通信、高校研究机构、互联网以及技术方等29家单位&#xf…

前端vue 动态加载ts文件,动态调用ts内的方法

业务场景: 在某个业务场景中, 我们需要在数据库配置ts文件路径,和需要调用的函数名称, 前端需要再指定的场景下,触发对应的函数, 并执行处理逻辑,返回结果. 实现: 这是一个数据库配置生成的动态表单 动态校验的例子, 需要引用动态的函数校验 任意一个js文件, common1.ts c…

运算符重载(上)

目录 运算符重载日期类的比较判断日期是否相等判断日期大小 赋值运算符重载赋值运算符重载格式赋值运算符只能重载成类的成员函数不能重载成全局函数用户没有显式实现时&#xff0c;编译器会生成一个默认赋值运算符重载&#xff0c;以值的方式逐字节拷贝 感谢各位大佬对我的支持…

Blender导出fbx模型,导入到ue5中模型丢失纹理材质

UE5系列文章目录 文章目录 UE5系列文章目录前言一、问题原因二、最终效果 前言 Blender导出fbx模型&#xff0c;导入到ue5中&#xff0c;发现模型丢失纹理材质&#xff0c;里面的原神人物模型妮露居然是白模&#xff0c;郁闷了大半天 一、问题原因 我在Blender导出fbx文件时…

如何高效创建与配置工程环境:零基础入门

新书上架~&#x1f447;全国包邮奥~ python实用小工具开发教程http://pythontoolsteach.com/3 欢迎关注我&#x1f446;&#xff0c;收藏下次不迷路┗|&#xff40;O′|┛ 嗷~~ 目录 一、工程环境的搭建与准备 二、配置虚拟环境与选择解释器 三、编写代码与自动添加多行注释 …

Mybatis Cache(一)MybatisCache+Redis

前面提到了&#xff0c;使用mybatis cache&#xff0c;一般是结合redis使用。 一、demo 1、数据表 create table demo.t_address (id int auto_incrementprimary key,address_name varchar(200) null,address_code varchar(20) null,address_type int n…

6.小程序页面布局 - 账单明细

文章目录 1. 6.小程序页面布局 - 账单明细1.1. 竞品1.2. 布局分析1.3. 布局demo1.4. 页面实现-头部1.5. 账单明细1.5.1. 账单明细-竞品分析1.5.2. 账单明细-实现1.5.2.1. 账单明细-实现-mock数据1.5.2.2. 每日收支数据的聚合整理1.5.2.3. 页面scroll-view 1.6. TODO 1. 6.小程序…

雷电预警监控系统:守护安全的重要防线

TH-LD1在自然界中&#xff0c;雷电是一种常见而强大的自然现象。它既有震撼人心的壮观景象&#xff0c;又潜藏着巨大的安全风险。为了有效应对雷电带来的威胁&#xff0c;雷电预警监控系统应运而生&#xff0c;成为现代社会中不可或缺的安全防护工具。 雷电预警监控系统的基本…

Convolutional Occupancy Networks【ECCV2020】

论文&#xff1a;https://arxiv.org/pdf/2003.04618 代码&#xff1a;GitHub - autonomousvision/convolutional_occupancy_networks: [ECCV20] Convolutional Occupancy Networks 图 1&#xff1a;卷积占据网络。传统的隐式模型 (a) 由于其全连接网络结构&#xff0c;表现能力…

政策及需求多因素驱动下 中国适老化改造市场空间大

政策及需求多因素驱动下 中国适老化改造市场空间大 适老化改造是为了提高老年人居住环境的舒适度和安全性&#xff0c;满足老年人居住需求进行的建筑改造&#xff0c;根据住房和城乡建设部城市建设司发布的《城市居家适老化改造指导手册》可以将适老化改造分为基础性改造和提升…

Spring Cloud 系列之Gateway:(9)初识网关

传送门 Spring Cloud Alibaba系列之nacos&#xff1a;(1)安装 Spring Cloud Alibaba系列之nacos&#xff1a;(2)单机模式支持mysql Spring Cloud Alibaba系列之nacos&#xff1a;(3)服务注册发现 Spring Cloud 系列之OpenFeign&#xff1a;(4)集成OpenFeign Spring Cloud …

【小笔记】如何在docker中更新或导入neo4j数据?

如何在docker中更新或导入neo4j数据&#xff1f; &#xff08;1&#xff09;背景&#xff1a; 我尝试了4.4.9和5.19.0版本的Neo4j社区版&#xff0c;基于他们的镜像创建容器后&#xff0c;需要导入我准备好的csv文件或dump文件&#xff0c;因为数据量非常大&#xff0c;所以采…

装备制造项目管理软件:奥博思PowerProject项目管理系统

数字化正逐步改变着制造方式和企业组织模式。某制造企业领导层透露&#xff0c;在采用数字化项目管理模式后&#xff0c;企业的发展韧性更加强劲&#xff0c;构筑起了竞争新优势&#xff0c;企业产品研制周期缩短25%&#xff0c;生产效率提升18%。 随着全球经济的发展&#xf…

北理工提出 LTrack 双摄像头系统 | 专注于暗场景多目标跟踪,自动驾驶和夜间监控的福音!

低光照场景在现实世界应用中很普遍&#xff08;例如自动驾驶和夜间监控&#xff09;。最近&#xff0c;在各种实际用例中的多目标跟踪受到了很多关注&#xff0c;但在暗场景中的多目标跟踪却鲜少被考虑。 在本文中&#xff0c;作者专注于暗场景中的多目标跟踪。为了解决数据集…