当前位置: 首页 > 工具软件 > mybatis-redis > 使用案例 >

MyBatis-Redis-Cache 实现缓存

东郭凯捷
2023-12-01

MyBatis-Redis-Cache:

           Mybatsi默认缓存对象 PerpetualCache,是本地缓存 。

将缓存数据存入redis操作过程:

定义缓存组件:

package com.vince.MyBatisCache;

import org.apache.ibatis.cache.Cache;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.context.ContextLoader;

import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class MyMyBatisCache implements Cache {

    private String id;  // 当前mapper的 namespace
    private final ReadWriteLock lock = new ReentrantReadWriteLock();
    RedisTemplate<String,Object> template;
    public MyMyBatisCache(){}  //无参构造

    public MyMyBatisCache(String id){  // mybatis 创建缓存组件实例时传入
        System.out.println("缓存id:"+id);
        this.id=id;
    }



    @Override
    public String getId() {
        return this.id;
    }

    //  缓存数据
    @Override
    public void putObject(Object key, Object value) {

        template.opsForValue().set(key.toString(), value);// 将查询结果存入 redis 缓存后备用

    }
    //  检查缓存
    @Override
    public Object getObject(Object key) {
        // 获取redis组件
         template =(RedisTemplate) ContextLoader.getCurrentWebApplicationContext().getBean("redisTemplate");
        System.out.println("检查缓存  key:"+key.getClass());
        Object cache = template.opsForValue().get(key.toString()); // 通过sql语句检查是否有缓存可用
        if (cache!=null){
            System.out.println("命中缓存~");
            return cache;
        }else{
            System.out.println("检查缓存 但是没有缓存数据~");
            return null;
        }
    }

    //删除某一个缓存数据
    @Override
    public Object removeObject(Object key) {
        template = (RedisTemplate) ContextLoader.getCurrentWebApplicationContext().getBean("redisTemplate");
        template.delete(key.toString() );
        return null;
    }


    // 当一个mapper中触发了一个写操作之后 清空所有缓存数据
    @Override
    public void clear() {
        System.out.println("nameSpace:"+this.getId()+"发生了写操作,清空了所有缓存数据~");
         template = (RedisTemplate) ContextLoader.getCurrentWebApplicationContext().getBean("redisTemplate");
        // 获取当前mapper下的所有缓存  key
        Set<String> keys = template.keys("*" + this.getId() + "*");
        // 删除 keys
        template.delete(keys);

    }

    @Override
    public int getSize() {
        return 0;
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return  this.lock;
    }
}

使用自定义的缓存组件:

<?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">
<!-- namespace:命名空间,用于隔离sql -->
<!-- 还有一个很重要的作用,使用动态代理开发DAO. namespace必须和Mapper接口类路径一致 -->
<mapper namespace="com.vince.dao.UserDao">
    <cache type="com.vince.MyBatisCache.MyMyBatisCache"></cache> // 使用自定义缓存组件

    <!--查寻所有-->
    <select id="selectAll" resultType="User">

        SELECT * FROM t_user

    </select>

</mapper>

Redis 配置文件:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- 连接池配置 -->
    <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
        <!-- 最多空闲连接数 -->
        <property name="maxIdle" value="1" />
        <!-- 最多有多少连接 -->
        <property name="maxTotal" value="5" />
        <property name="minIdle" value="1"></property>
        <!-- 连接数用完时,是否阻塞,阻塞超过maxWaitMillis会抛出异常 -->
        <property name="blockWhenExhausted" value="true" />
        <!-- 检出连接时,最大等待时长 -->
        <property name="maxWaitMillis" value="30000" />
        <!-- 在检出时是否检测 -->
        <property name="testOnBorrow" value="false" />
        <!-- 空闲时是否检测连接是否可用 -->
        <property name="testWhileIdle" value="false"></property>
        <!-- Evict=驱逐  连接至少要空闲多少时间才会成为可以被驱逐线程扫描并移除 -->
        <property name="minEvictableIdleTimeMillis" value="60000"></property>
        <!-- 驱逐线程 两次驱逐之间要sleep的时间 如果小于0,则不会有驱逐线程,则minEvictableIdleTimeMillis无效-->
        <property name="timeBetweenEvictionRunsMillis" value="30000"></property>
        <!-- 驱逐线程每次最多扫描几个连接 -->
        <property name="numTestsPerEvictionRun" value="3"></property>
        <!-- last in first out 检出策略 后入先出  或 先入先出 -->
        <property name="lifo" value="true"></property>
    </bean>


    <!-- 连接Factory -->
    <bean id="jedisConnectionFactory"
          class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
        <!-- Redis主机 -->
        <property name="hostName" value="192.168.11.128"></property>
        <property name="port" value="8000"></property>
        <!-- 连接池配置信息 -->
        <property name="poolConfig" ref="jedisPoolConfig"></property>
    </bean>

    <!-- 如果没有设置序列化,则默认使用DefaultSerializer。
		 声明序列化组件
    -->
    <bean id="ss" class="org.springframework.data.redis.serializer.StringRedisSerializer" />
    <bean class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"      			id="jacks" />
    <bean class="com.alibaba.fastjson.support.spring.GenericFastJsonRedisSerializer" id="fast"></bean>

    <!-- RedisTemplate:核心组件 -->
    <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
          p:connectionFactory-ref="jedisConnectionFactory"
          p:keySerializer-ref="ss"
          p:hashKeySerializer-ref="ss"
          p:hashValueSerializer-ref="fast"
          p:stringSerializer-ref="ss"
          p:valueSerializer-ref="fast"></bean>

</beans>

在Spring 工厂中导入 redis 配置文件:

<!--导入redis-->
 <import resource="classpath:applicationContext-redsi.xml"></import>

 

 类似资料: