精华内容
下载资源
问答
  • 1、什么是Redis二级缓存 2、需求 3、步骤分析与实战(具体事例) 4、测试 5、总结 什么是Redis二级缓存 Redis的二级缓存就是:控制器第一次查询是Mybatis对数据库进行查询,从数据库查询到的数据通过配置文件与Redis...

    使用Redis做MyBatis的二级缓存

    目录

    1、什么是Redis二级缓存
    2、需求
    3、步骤分析与实战(具体事例)
    4、测试
    5、总结

    什么是Redis二级缓存

    Redis的二级缓存就是:控制器第一次查询是Mybatis对数据库进行查询,从数据库查询到的数据通过配置文件与RedisCache类将数据缓存到Redis中,当需要第二次查询相同数据时,就会从Redis中取出缓存的内容,而不会查询数据库,减轻了数据库的压力,查询更迅速。当提交修改此条数据的内容的代码时,会执行commit操作,Redis就会清空之前缓存的数据,而缓存修改后的最新的数据,此时显示页面不管怎么刷新,都是去Redis中取出缓存的最新数据。

    需求

    第一次根据用户姓名查询用户信息

     select * from user where username=?
    

    分析:
    第一次根据用户姓名查询用户信息,根据控制台的日志,查看数据库执行操作步骤。

    第二次根据姓名查询同一个用户信息

     select * from user where username=?
    

    分析:
    第二次根据用户姓名查询用户信息,根据控制台的日志,查看数据库执行操作步骤。

    步骤分析

    ①、需要配置好SSM的开发环境,导包,下面是redis需要的包
    在这里插入图片描述
    ②、在Mybatis的配置文件中开启缓存设置
    在这里插入图片描述
    代码:

     <settings>
            <!-- 全局映射器启用缓存 *主要将此属性设置完成即可 -->
            <setting name="cacheEnabled" value="true" />
    
            <!-- 查询时,关闭关联对象即时加载以提高性能 -->
            <setting name="lazyLoadingEnabled" value="false" />
    
            <!-- 设置关联对象加载的形态,此处为按需加载字段(加载字段由SQL指 定),不会加载关联表的所有字段,以提高性能 -->
            <setting name="aggressiveLazyLoading" value="true" />
        </settings>
    

    ③、配置Redis配置文件
    在这里插入图片描述
    ④、spring配置文件applicationContext.xml中加载redis.properties配置文件
    在这里插入图片描述
    代码:

    <context:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true"/>
    
    	<!-- redis数据源 -->
    	<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
    		<property name="maxIdle" value="${redis.maxIdle}" />
    		<property name="maxTotal" value="${redis.maxActive}" />
    		<property name="maxWaitMillis" value="${redis.maxWait}" />
    		<property name="testOnBorrow" value="true"></property>
    	</bean>
    
    	<!-- Spring-redis连接池管理工厂 -->
    	<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
    		<property name="hostName" value="${redis.host}" />
    		<property name="port" value="${redis.port}" />
    		<property name="password" value="${redis.pass}" />
    		<property name="poolConfig" ref="poolConfig" />
    	</bean>
    
    	<!-- 使用中间类解决RedisCache.jedisConnectionFactory的静态注入,从而使MyBatis实现第三方缓存 -->
    	<!-- <bean id="redisCacheTransfer" class="com.redis.RedisCacheTransfer">
            <property name="jedisConnectionFactory" ref="jedisConnectionFactory" />
        </bean> -->
    
    
    	<!-- Redis  配置 -->
    	<bean id="jedis" class="redis.clients.jedis.Jedis">
    		<constructor-arg value="192.168.1.14" index="0" type="java.lang.String"/>
    		<constructor-arg value="6379" index="1"/>
    	</bean>
    

    ⑤、第三方内存数据库Redis,定义一个RedisCache实现org.apache.ibatis.cache.Cache接口
    在这里插入图片描述
    代码:(直接使用就可以,不需里面具体结构)

    package com.xlj.redis;
    
    import org.apache.ibatis.cache.Cache;
    import org.springframework.data.redis.connection.RedisConnection;
    import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
    import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
    import org.springframework.data.redis.serializer.RedisSerializer;
    import redis.clients.jedis.exceptions.JedisConnectionException;
    
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    /**
     *
     * @ClassName:RedisCache.java
     *
     * @Description:使用第三方内存数据库Redis作为二级缓存
     *
     *
     *
     */
    public class RedisCache implements Cache {
        /**
         * 静态成员变量无法直接使用spring注解注入
         */
        private static JedisConnectionFactory jedisConnectionFactory;
    
        private final String id;
    
        /**
         * The {@code ReadWriteLock}.
         */
        private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
    
        public RedisCache(final String id) {
            if (id == null) {
                throw new IllegalArgumentException("Cache instances require an ID");
            }
            this.id = id;
        }
    
        public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
            RedisCache.jedisConnectionFactory = jedisConnectionFactory;
        }
    
        public void clear() {
            RedisConnection connection = null;
            try {
                connection = jedisConnectionFactory.getConnection();
                connection.flushDb();
                connection.flushAll();
    
            } catch (JedisConnectionException e) {
                e.printStackTrace();
    
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
        }
    
        public String getId() {
            return this.id;
        }
    
        public Object getObject(Object key) {
            Object result = null;
            RedisConnection connection = null;
    
            try {
                connection = jedisConnectionFactory.getConnection();
                RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
                result = serializer.deserialize(connection.get(serializer.serialize(key)));
    
            } catch (JedisConnectionException e) {
                e.printStackTrace();
    
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
    
            return result;
        }
    
        public void putObject(Object key, Object value) {
            RedisConnection connection = null;
            try {
                connection = jedisConnectionFactory.getConnection();
                RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
                connection.set(serializer.serialize(key), serializer.serialize(value));
            } catch (JedisConnectionException e) {
                e.printStackTrace();
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
        }
    
        public Object removeObject(Object key) {
            RedisConnection connection = null;
            Object result = null;
            try {
                connection = jedisConnectionFactory.getConnection();
                RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();
                result = connection.expire(serializer.serialize(key), 0);
            } catch (JedisConnectionException e) {
                e.printStackTrace();
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
            return result;
        }
    
        public ReadWriteLock getReadWriteLock() {
            // TODO Auto-generated method stub
            return this.readWriteLock;
        }
    
        public int getSize() {
            int result = 0;
            RedisConnection connection = null;
    
            try {
                connection = jedisConnectionFactory.getConnection();
                result = Integer.valueOf(connection.dbSize().toString());
    
            } catch (JedisConnectionException e) {
                e.printStackTrace();
    
            } finally {
                if (connection != null) {
                    connection.close();
                }
            }
            return result;
        }
    }
    

    ⑥、由于Spring无法注入静态成员变量,所以定义一个静态注入中间类
    在这里插入图片描述
    代码:

    package com.xlj.redis;
    
    /**
     * Created by yutao on 18/11/14.
     */
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
    import org.springframework.stereotype.Component;
    
    @Component
    public class RedisCacheTransfer {
    
        @Autowired
        public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) {
            RedisCache.setJedisConnectionFactory(jedisConnectionFactory);
        }
    }
    

    ⑦、UserMapper.xml中需要开启本mapper的namespace的缓存,指定接口的实现类
    在这里插入图片描述

    其中最重要的就是:<cache eviction="LRU"type="com.redis.RedisCache" />
    

    ⑧、User序列化
    在这里插入图片描述
    代码:

    package com.xlj.po;
    
    import java.io.Serializable;
    import java.util.Date;
    
    public class User implements Serializable{
        private Integer id;
    
        private String username;
    
        private Date birthday;
    
        private String sex;
    
        private String address;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username == null ? null : username.trim();
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex == null ? null : sex.trim();
        }
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address == null ? null : address.trim();
        }
    
        @Override
        public String toString() {
            return "User{" +
                    "id=" + id +
                    ", username='" + username + '\'' +
                    ", birthday=" + birthday +
                    ", sex='" + sex + '\'' +
                    ", address='" + address + '\'' +
                    '}';
        }
    }
    

    ⑨控制器RedisController中:
    在这里插入图片描述
    ⑩、浏览器访问

    http://localhost:8080/redis/checkUser.do?username=小龙
    

    要用数据中已有的名字。。。

    测试

    《1》验证查询
    ①、第一次根据用户姓名查询用户信息,根据控制台的日志,查看数据库执行操作步骤。
    在这里插入图片描述
    分析:
    第一次查询从数据库中查询,执行了sql语句!

    ②、第二次根据用户姓名查询用户信息,根据控制台的日志,查看数据库执行操作步骤
    在这里插入图片描述
    分析:
    第二次查询发现没有执行sql语句,也查询出了数据,说明第二次查询是从redis中查询出的缓存数据

    ③、查看redis缓存,已经缓存了查询的操作
    在这里插入图片描述
    《2》验证修改(修改刚才查询到的保存在redis中那条数据)后查询(查询同样的语句),判断redis中的数据是否修改了

    1、SSM修改的过程这里就不介绍了,先修改不进行查询,查看执行修改之后,redis中的数据变化,结果如下:
    在这里插入图片描述
    分析:修改之后先不进行查询,查看Redis,发现Redis中之前缓存的数据被清空了,(因为修改执行了commit操作,所以清空了)
    2、此时再次执行查询操作,再次通过日志验证是从哪里查询的,如下图:
    在这里插入图片描述
    分析:由图可知,再次执行了sql语句,所以再次验证了修改之后Redis中的数据被清空了
    3、此时再次重启服务器,再进行查询,再次判断从哪里取出的数据,如下图:
    在这里插入图片描述
    分析:由图可知,数据是从Redis中取出来的,而取出来的数据是最新数据。说明当修改之后redis中的数据被清空,而当我们再次执行查询时,redis中又缓存了查询到的新的数据,此时我们再次重启服务进行查询,就又是从redis缓存中获取,而此时获取到的就是最新数据!

    总结:

    控制器第一次查询是Mybatis对数据库进行查询,从数据库查询到的数据通过配置文件与RedisCache类将数据缓存到Redis中,当需要第二次查询相同数据时,就会从Redis中取出缓存的内容,而不会查询数据库,减轻了数据库的压力,查询更迅速。当提交修改此条数据的内容的代码时,会执行commit操作,Redis就会清空之前缓存的数据,此时再查询此条数据,Redis就会缓存修改后的最新的数据,此时显示页面刷新再去查询,就又是去Redis中取出缓存的最新数据。

    展开全文
  • springboot ehcache + redis 二级缓存 自建 RedisEhcacheCacheManager类实现 CacheManager ,自定义里面的逻辑 本地ehcache,分布式redis缓存

    springboot ehcache + redis 二级缓存
    自建 RedisEhcacheCache 类实现 Cache
    自建 RedisEhcacheCacheManager类实现 CacheManager ,自定义里面的逻辑
    本地ehcache,分布式redis缓存

    hset key field value
    @Cacheable的value参数是hset命令的key字段, 而@Cacheable的key参数是hset命令的field字段,
    @Cacheable注解所在的函数返回值是hset命令的value字段

    展开全文
  • Mybatis默认没有开启二级缓存,需要在全局配置(mybatis-config.xml)中开启二级缓存。本文讲述的是使用Redis作为缓存,与springboot、mybatis进行集成的方法。需要的朋友参考下吧
  • mybatis与redis二级缓存总结

    千次阅读 2019-04-12 09:37:27
    二、Mybatis映射文件使用二级缓存 mapper级标签 语句级 三、Redis缓存工具类 mybatis二级缓存接口 redis-string缓存工具类 putObject getObject Clear redis-HashMap缓存工具类 putObject getObject ...

    目录

    一、在spring boot 环境整合

    二、Mybatis映射文件使用二级缓存

    mapper级标签

    语句级

    三、Redis缓存工具类

    mybatis二级缓存接口

    redis-string缓存工具类

    putObject

    getObject

    Clear

    redis-HashMap缓存工具类

    putObject

    getObject

    clear

    四、使用Mybatis二级缓存的注意事项


    一、在spring boot 环境整合

    https://blog.csdn.net/xushiyu1996818/article/details/89036631

    二、Mybatis映射文件使用二级缓存

    mapper级标签

        <!--
        eviction LRU
        flushInterval缓存时间,以毫秒为单位
        size缓存大小
        readOnly如果为false的话,缓存对象必须是可序列化的-->
        <cache eviction="LRU"
               type="com.xusy.util.MybatisCacheRedisMap"
               flushInterval="120000"
               size="1024"
               readOnly="true"/>

    开启二级缓存,在XML配置文件中添加Cache节点即可,

    eviction为缓存的策略有, 默认的是 LRU:

    LRU – 最近最少使用的:移除最长时间不被使用的对象。

    FIFO – 先进先出:按对象进入缓存的顺序来移除它们。

    SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象。

    WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象。

    type为使用的redis缓存工具类

    flushInterval为缓存时间,以毫秒为单位,此时为120秒

    size为保存多少个结果,现在为1024个

    readOnly为是否是只读的,现在为true,在不同线程中的调用者之间修改它们会 导致冲突

    只读的缓存会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改的,这样性能会好一些,缺点是因为他是只读的,所以不能被修改。如果设置为false的话,读写的缓存会通过序列化返回该缓存对象的拷贝,因为会把对象进行拷贝,这会慢一些,但是安全,因此默认是 false。

    cache-ref标签

    <cache-ref namespace="mapper.StudentMapper"/>

    cache-ref代表引用别的命名空间的Cache配置,两个命名空间的操作使用的是同一个Cache。(这个当语句涉及联表操作要用到)

     

    语句级

    一旦在mapper里面写了cache标签,整个mapper的所有语句,都会默认使用缓存,默认方式如下

    当为select语句时:

    flushCache默认为false,表示任何时候语句被调用,都不会去清空本地缓存和二级缓存。

    useCache默认为true,表示会将本条语句的结果进行二级缓存。

    当为insert、update、delete语句时:

    flushCache默认为true,表示任何时候语句被调用,都会导致本地缓存和二级缓存被清空。

    useCache属性在该情况下没有。

    当为select语句的时候,如果没有去配置flushCache、useCache,那么默认是启用缓存的,所以,如果有必要,那么就需要人工修改配置,修改结果类似下面:

    <select id="save" parameterType="XX" flushCache="true" useCache="false">
        ……
    </select>


    update 的时候如果 flushCache="false",则当你更新后,查询的数据数据还是老的数据。
     

    三、Redis缓存工具类

    mybatis二级缓存接口

    /*jadclipse*/// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
    
    package org.apache.ibatis.cache;
    
    import java.util.concurrent.locks.ReadWriteLock;
    
    public interface Cache
    {
    
        public abstract String getId();
    
        public abstract void putObject(Object obj, Object obj1);
    
        public abstract Object getObject(Object obj);
    
        public abstract Object removeObject(Object obj);
    
        public abstract void clear();
    
        public abstract int getSize();
    
        public abstract ReadWriteLock getReadWriteLock();
    }
    
    
    

    总共分为7个方法,最重要的是put,get,clear方法

    分别会在缓存加入(第一次select),缓存命中(第二次select),缓存清除(insert,update,delete时)

    在mapper里的cache标签里的type的属性就是实现了这个cache接口的缓存工具类

    redis-string缓存工具类

    package com.xusy.util;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    import org.apache.ibatis.cache.Cache;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.data.redis.core.HashOperations;
    import org.springframework.data.redis.core.RedisCallback;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.ValueOperations;
    
    public class MybatisCacheRedisString implements Cache {
        private static final Logger logger = LoggerFactory.getLogger(MybatisCacheRedisString.class);
        private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        private final String id; 
        private RedisTemplate redisTemplate;
        private static final long EXPIRE_TIME_IN_MINUTES = 30; // redis过期时间
        public MybatisCacheRedisString(String id) {
            if (id == null) {
                throw new IllegalArgumentException("Cache instances require an ID");
            }
            this.id = id;
            logger.debug("创建了mybatis的redis缓存"+id);
        }
        @Override
        public String getId() {
            return id;
        }
        /**
         * Put query result to redis
         *
         * @param key
         * @param value
         */
        @Override
        @SuppressWarnings("unchecked")
        public void putObject(Object key, Object value) {
            RedisTemplate redisTemplate = getRedisTemplate();
            //redisTemplate进行value操作(key-string)
            ValueOperations opsForValue = redisTemplate.opsForValue();
            //进行字符串操作,放入key和value,redis过期时间=EXPIRE_TIME_IN_MINUTES
            opsForValue.set(key, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);
            logger.debug("redis cache "+id+" put key: "+key.toString()+" value: "+value.toString());
        }
        /**
         * Get cached query result from redis
         *
         * @param key
         * @return
         */
        @Override
        public Object getObject(Object key) {
            RedisTemplate redisTemplate = getRedisTemplate();
            ValueOperations opsForValue = redisTemplate.opsForValue();
            logger.debug("redis cache "+id+" get key: "+key.toString());
            //得到key的value
            return opsForValue.get(key);
        }
        /**
         * Remove cached query result from redis
         *
         * @param key
         * @return
         */
        @Override
        @SuppressWarnings("unchecked")
        public Object removeObject(Object key) {
            RedisTemplate redisTemplate = getRedisTemplate();
            //删除这个key
            redisTemplate.delete(key);
            logger.debug("redis cache "+id+" remove key: "+key.toString());
            return null;
        }
        /**
         * Clears this cache instance
         */
        @Override
        public void clear() {
            RedisTemplate redisTemplate = getRedisTemplate();
            redisTemplate.execute((RedisCallback) connection -> {
            	//将数据库清空
                connection.flushDb();
                return null;
            });
            logger.debug("Clear all the cached query result from redis "+id);
        }
        @Override
        public int getSize() {
            return 0;
        }
        @Override
        public ReadWriteLock getReadWriteLock() {
            return readWriteLock;
        }
        private RedisTemplate getRedisTemplate() {
            if (redisTemplate == null) {
                redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
            }
            return redisTemplate;
        }
    }
    

    查看一条日志

    2019-04-11 16:59:20.597 DEBUG 19980 --- [nio-8080-exec-9] com.xusy.util.MybatisCacheRedisMap       : redis cache com.xusy.dao.UserMapper2 put key: -1962129931:1974203225:com.xusy.dao.UserMapper2.findById:0:2147483647:select * from user  where id=?:2:SqlSessionFactoryBean value: [ ]

    这个mybatisCacheRedisString 缓存工具类有以下几个属性

    readwritelock:读写锁,每个工具类实例各一个,并通过接口提供出去

    id:工具类实例的标识,上面的例子就是com.xusy.dao.UserMapper2,就是这个mapper的namespace,可以看到不同mapper使用的工具类实例不同

    redisTemplate:通过另外一个工具类applicationContextHolder从spring容器中获得。

    putObject

            //redisTemplate进行value操作(key-string)
            ValueOperations opsForValue = redisTemplate.opsForValue();
            //进行字符串操作,放入key和value,redis过期时间=EXPIRE_TIME_IN_MINUTES
            opsForValue.set(key, value, EXPIRE_TIME_IN_MINUTES, TimeUnit.MINUTES);

    先得到string操作的模板ValueOperations

    然后进行string操作,key=key,value=value

    可以看到上面那一次:key=-1962129931:1974203225:com.xusy.dao.UserMapper2.findById:0:2147483647:select * from user  where id=?:2:SqlSessionFactoryBean

    相当于是mapper的包+方法+sql语句+sql参数

    value为[]  相当于是返回的结果,也可以是value: [User [id=4, name=xsy, age=10]]

    getObject

    从数据库里得到key为key,字符串的结果

    Clear

    redisTemplate.execute((RedisCallback) connection -> {
            	//将数据库清空
                connection.flushDb();
                return null;
            });

    可以看到这个clear操作将整个redis数据库清空,包括不属于这个namespace的数据,需要改进

     

    redis-HashMap缓存工具类

    package com.xusy.util;
    
    import java.util.concurrent.TimeUnit;
    import java.util.concurrent.locks.ReadWriteLock;
    import java.util.concurrent.locks.ReentrantReadWriteLock;
    
    import org.apache.ibatis.cache.Cache;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.data.redis.core.HashOperations;
    import org.springframework.data.redis.core.RedisCallback;
    import org.springframework.data.redis.core.RedisTemplate;
    import org.springframework.data.redis.core.ValueOperations;
    
    public class MybatisCacheRedisMap implements Cache {
        private static final Logger logger = LoggerFactory.getLogger(MybatisCacheRedisMap.class);
        private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        private final String id; // 在构造函数自动注入,为namespace的名字
        private RedisTemplate redisTemplate;
        private static final long EXPIRE_TIME_IN_MINUTES = 30; // redis过期时间
        public MybatisCacheRedisMap(String id) {
            if (id == null) {
                throw new IllegalArgumentException("Cache instances require an ID");
            }
            this.id = id;
            logger.debug("创建了mybatis的redis缓存"+id);
        }
        @Override
        public String getId() {
            return id;
        }
        /**
         * Put query result to redis
         *
         * @param key
         * @param value
         */
        @Override
        @SuppressWarnings("unchecked")
        public void putObject(Object key, Object value) {
            RedisTemplate redisTemplate = getRedisTemplate();
            HashOperations opsForHash=redisTemplate.opsForHash();
            opsForHash.put(id,key,value);
            logger.debug("redis cache "+id+" put key: "+key.toString()+" value: "+value.toString());
        }
        /**
         * Get cached query result from redis
         *
         * @param key
         * @return
         */
        @Override
        public Object getObject(Object key) {
            RedisTemplate redisTemplate = getRedisTemplate();
            HashOperations opsForHash=redisTemplate.opsForHash();
            logger.debug("redis cache "+id+" get key: "+key.toString());
            return opsForHash.get(id, key);
        }
        /**
         * Remove cached query result from redis
         *
         * @param key
         * @return
         */
        @Override
        @SuppressWarnings("unchecked")
        public Object removeObject(Object key) {
            RedisTemplate redisTemplate = getRedisTemplate();
            logger.debug("redis cache "+id+" remove key: "+key.toString());
            HashOperations opsForHash=redisTemplate.opsForHash();
            opsForHash.delete(id, key);
            return null;
        }
        /**
         * Clears this cache instance
         */
        @Override
        public void clear() {
            RedisTemplate redisTemplate = getRedisTemplate();
            redisTemplate.execute((RedisCallback) connection -> {
            	redisTemplate.delete(id);
                return null;
            });
            logger.debug("Clear all the cached query result from redis "+id);
        }
        @Override
        public int getSize() {
            return 0;
        }
        @Override
        public ReadWriteLock getReadWriteLock() {
            return readWriteLock;
        }
        private RedisTemplate getRedisTemplate() {
            if (redisTemplate == null) {
                redisTemplate = ApplicationContextHolder.getBean("redisTemplate");
            }
            return redisTemplate;
        }
    }
    

     

    putObject

    HashOperations opsForHash=redisTemplate.opsForHash();
            opsForHash.put(id,key,value);

     

    可以看到这次的put操作,是以id为key(就是namespace为key),数据结构是hashmap,map里的key为key,value为value

    getObject

    HashOperations opsForHash=redisTemplate.opsForHash();
            logger.debug("redis cache "+id+" get key: "+key.toString());
            return opsForHash.get(id, key);

    这个get操作,是以id为key,取出hashmap中key=key的value

    clear

    redisTemplate.delete(id);

    在mybatis缓存工具类中hashmap优于string的原因就是这个clear操作,string的clear是将数据库清空,而hashmap的clear是将key为id的value删除,不会删除其他namespace(key为其他id)的缓存数据

    四、使用Mybatis二级缓存的注意事项

    在一个命名空间下使用二级缓存
    二级缓存对于不同的命名空间namespace的数据是互不干扰的,倘若多个namespace中对一个表进行操作的话,就会导致这不同的namespace中的数据不一致的情况。

    在单表上使用二级缓存
    在做关联关系查询时,就会发生多表的操作,此时有可能这些表存在于多个namespace中,这就会出现上一条内容出现的问题了。

    查询多于修改时使用二级缓存
    在查询操作远远多于增删改操作的情况下可以使用二级缓存。因为任何增删改操作都将刷新二级缓存,对二级缓存的频繁刷新将降低系统性能。

     

    展开全文
  • 2springboot +mybatis+redis二级缓存小demo 1 先看核心代码打印出效果图 打印输出内容如下: 调用Redis缓存Key : com.sun.proxy.$Proxy77getAccountCheckStatisticsAccountCheckStatisticsPageDto...

     1  先看核心代码打印出效果图

     2 springboot +mybatis+redis二级缓存小demo

     

    1  先看核心代码打印出效果图   

     


     

    打印输出内容如下:

     

    调用Redis缓存Key : com.sun.proxy.$Proxy77getAccountCheckStatisticsAccountCheckStatisticsPageDto(pageNumber=1, pageSize=15, offSet=0, partnername=null, beginTime=2018-02-02, endTime=2019-05-23)
    2019-05-23 20:36:08.715  INFO 11752 --- [nio-8085-exec-5] c.e.d.s.impl.AccountCheckServiceImpl     : ------------------>1086
    调用Redis缓存Key : com.sun.proxy.$Proxy77getAccountCheckStatisticsAccountCheckStatisticsPageDto(pageNumber=1, pageSize=15, offSet=0, partnername=null, beginTime=2018-02-02, endTime=2019-05-23)
    2019-05-23 20:38:36.705  INFO 11752 --- [nio-8085-exec-7] c.e.d.s.impl.AccountCheckServiceImpl     : ------------------>59  
    调用Redis缓存Key : com.sun.proxy.$Proxy77getAccountCheckStatisticsAccountCheckStatisticsPageDto(pageNumber=1, pageSize=15, offSet=0, partnername=null, beginTime=2018-02-02, endTime=2019-05-23)
    2019-05-23 20:38:40.662  INFO 11752 --- [nio-8085-exec-8] c.e.d.s.impl.AccountCheckServiceImpl     : ------------------>6 
    调用Redis缓存Key : com.sun.proxy.$Proxy77getAccountCheckStatisticsAccountCheckStatisticsPageDto(pageNumber=5, pageSize=15, offSet=60, partnername=null, beginTime=2018-02-02, endTime=2019-05-23) 
    2019-05-23 20:43:11.600  INFO 11752 --- [nio-8085-exec-2] c.e.d.s.impl.AccountCheckServiceImpl     : ------------------>153  
    调用Redis缓存Key : com.sun.proxy.$Proxy77getAccountCheckStatisticsAccountCheckStatisticsPageDto(pageNumber=5, pageSize=15, offSet=60, partnername=null, beginTime=2018-02-02, endTime=2019-05-23)
    2019-05-23 20:43:17.879  INFO 11752 --- [nio-8085-exec-4] c.e.d.s.impl.AccountCheckServiceImpl     : ------------------>7   
    调用Redis缓存Key : com.sun.proxy.$Proxy77getAccountCheckStatisticsAccountCheckStatisticsPageDto(pageNumber=8, pageSize=15, offSet=105, partnername=null, beginTime=2018-02-02, endTime=2019-05-23)
    2019-05-23 20:43:23.719  INFO 11752 --- [nio-8085-exec-3] c.e.d.s.impl.AccountCheckServiceImpl     : ------------------>143
    2019-05-23 20:43:33.068  INFO 11752 --- [nio-8085-exec-6] c.e.d.controller.AccountCheckController  :  
    调用Redis缓存Key : com.sun.proxy.$Proxy77getAccountCheckStatisticsAccountCheckStatisticsPageDto(pageNumber=8, pageSize=15, offSet=105, partnername=null, beginTime=2018-02-02, endTime=2019-05-23)
    2019-05-23 20:43:33.076  INFO 11752 --- [nio-8085-exec-6] c.e.d.s.impl.AccountCheckServiceImpl     : ------------------>4
     

     

    程序输出的结果集:这是一个分页查询语句的执行参数以及执行时间,

    pageNumber是1,第一次用时1086 ms,第二次用时59 ms, 第三次6 ms

    pageNumber是5,第一次用时153 ms,第二次用时7 ms

    pageNumber是8,第一次用时143 ms,第二次用时4 ms

     

    2   springboot +mybatis+redis二级缓存小demo

     

    展开全文
  • 本文主要对mybatis plus结合redis二级缓存的学习总结,里面涉及mybatis plus和redis的相关知识,本文会持续更新,不断地扩充 本文仅为记录学习轨迹,如有侵权,联系删除 一、mybatis plus 具体的相关知识建议去...
  • Spring Boot + Mybatis + Redis二级缓存

    千次阅读 2017-07-07 14:52:10
    Spring Boot + Mybatis + Redis二级缓存 背景 Spring-Boot因其提供了各种开箱即用的插件,使得它成为了当今最为主流的Java Web开发框架之一。Mybatis是一个十分轻量好用的ORM框架。Redis是当今十分主流的分布式key...
  • 目录背景Mybatis的一级缓存(默认开启)Mybatis的二级缓存二级缓存开启方式二级缓存存在的问题Mybatis使用redis缓存自定义Mybatis二级缓存的实现类使用自定义缓存实现类Mybatis延迟加载 MyBatis 是一款优秀的持久层...
  • Spring Boot + Mybatis + Redis二级缓存实例

    万次阅读 2017-06-29 15:27:12
    二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据...
  • 各位同学在使用redis搭建二级缓存的 过程中,按照 网上很多的教程搭建成功了。 但是会遇到一种情况,那就是使用 二级缓存,并刷新Cache的时候,会清空一次所有的缓存,Mapper的代码段如下: &lt;select id=&...
  • 有一老项目采用的hibernate配合ehcache作为二级缓存,现因需求需要更换redis来做hibernate的二级缓存。大家不用问为什么不换掉hibernate,因为是老项目所以风险太大。 问题: 1、我按照网上做法导入了若干个jar包...
  • @RequestMapping("/redis") public class RedisController { /** *cacheNames 相当于一个文件夹 *key 注意 key里边一定要加一个单引号 不加就会报错 * 还要注意实体对象一定要实现序列化接口 * @return * @...
  • mybatis+redis二级缓存

    2017-11-16 10:38:30
    项目使用的是spring+mybatis+mysql5.5 系统运行后一旦执行复杂查询 mysql 服务器cpu疯狂飙升(为什么要执行复杂查询 ... 然后加缓存 先上mybatis的一级缓存 ,但是查资料说是只在一个sqlSession下有效。我在service方法
  • echache+redis二级缓存

    2018-07-16 15:07:32
    本文主要介绍为什么要构建ehcache+redis级缓存?以及在实战中如何实现?思考如何配置缓存策略更合适?这样的方案可能遗留什么问题?JUST DO IT! GO!问题描述场景:我们的应用系统是分布式集群的,可横向扩展的。...
  • 文章目录一级缓存二级缓存开启 MyBatis 二级缓存实体类实现序列化接口并声明序列号IDEA 提示生成序列号创建相关工具类 一级缓存 MyBatis 会在表示会话的 SqlSession 对象中建立一个简单的缓存,将每次查询到的结果...
  • 这几天补充了下文档,这里接《Spring Cloud终篇 | 总结 一:一个完整的企业级SpringCloud架构(Mybatis--多数据源)》之后,简述一下Redis二级缓存及feign的调用方式。 源码案例:...
  • --Spring Redis RedisAutoConfiguration--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </...
  • 二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕会将数据库中查询的数据...
  • Mybatis-Redis二级缓存分布式实现

    千次阅读 2019-03-18 10:46:45
    Mybatis二级缓存默认采用的org.apache.ibatis.cache.impl.PerpetualCache实现的(基于内存中Map<Object, Object> cache),在项目进行分布式部署时,无法保证多实例间的分布式缓存一致性,故需要对该Cache实现...
  • MyBatis -- 整合Redis二级缓存

    千次阅读 2018-01-17 21:31:36
    MyBatis一级二级缓存     一级缓存:    MyBatis一级缓存为SqlSession级别的缓存,默认开启,相同的SqlSession对象查询相同条件的结果时,如果存在一级缓存,那么只会访问数据库一次,一级缓存在sqlSession...
  • 1.pom.xml导入依赖 org.apache.commons commons-pool2 org.springframework.boot spring-boot-starter-data-redis org.springframework.data spring-data-redis 2.bootstrap.yml开启缓存,配置数据库和redis基本信息...
  • 环境 :IDEAR+MySQL+RDM
  • 开启 MyBatis 二级缓存 在 Spring Boot 配置文件中开启 MyBatis 二级缓存,配置代码如下: mybatis: configuration: cache-enabled: true 实体类实现序列化接口并声明序列号 private static final long ...
  • springBoot+springSecurity+jwt+Redis二级缓存

    千次阅读 2019-04-25 09:52:50
    Redis作为二级缓存 0.从QQ群下载解压 redis.zip - 启动redis服务器: redis-server 1.pom.xml中增加redis的依赖 org.springframework.boot spring-boot-starter-data-redis 2.application.properties中...
  • Redis是当今十分主流的分布式key-value型数据库,在web开发中,我们常用它来缓存数据库的查询结果。 本篇博客将介绍如何使用Spring-Boot快速搭建一个Web应用,并且采用Mybatis作为我们的ORM框架。为了

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 71,412
精华内容 28,564
关键字:

redis二级缓存

redis 订阅