真正的mybatis_redis二级缓存

网上流传的代码缓存失效存在严重问题。

思路....以后再细说

目前的方案还不够完美,失效力度控制不够细。

主要代码

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.ibatis.cache.Cache;
import org.apache.log4j.Logger;

import redis.clients.jedis.Jedis;

/*
 * 使用第三方缓存服务器,处理二级缓存
 * zuimao
 */
public class RedisCache implements Cache {

    private static final Logger logger = Logger.getLogger(RedisCache.class);

    /** The ReadWriteLock. */
    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    private final String COMMON_CACHE_KEY = "MYBATIS:";
    private static final String UTF_8 = "utf-8";

    /**
     * 按照一定规则标识key
     */
    private String getKey(Object key) {
        StringBuilder accum = new StringBuilder();
        accum.append(COMMON_CACHE_KEY);
        accum.append(this.id).append(":");
        accum.append(DigestUtils.md5Hex(String.valueOf(key)));
        return accum.toString();
    }

    /**
     * redis key规则前缀
     */
    private String getKeys() {
        return COMMON_CACHE_KEY + this.id + ":*";
    }

    private String id; 

    public RedisCache() {
    }

    public RedisCache(final String id) {
        if (id == null) {
            throw new IllegalArgumentException("必须传入ID");
        }
        logger.debug("MybatisRedisCache:id=" + id);
        this.id = id;
    }

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

    @Override
    public int getSize() {
        Jedis jedis = null;
        int result = 0;
        try {
            jedis = RedisStandAloneUtil.getJedisPool().getResource();
            Set<byte[]> keys = jedis.keys(getKeys().getBytes(UTF_8));
            if (null != keys && !keys.isEmpty()) {
                result = keys.size();
            }
            logger.debug(this.id+"---->>>>总缓存数:" + result);
        } catch (Exception e) {
        	 logger.error(e.getMessage(), e);
        } finally {
        	if (jedis != null) {
                jedis.close();
            }

        }
        return result;
    }

    @Override
    public void putObject(Object key, Object value) {
        Jedis jedis = null;
        try {
            jedis = RedisStandAloneUtil.getJedisPool().getResource();
            byte[] keys = getKey(key).getBytes(UTF_8);
            jedis.set(keys, SerializeUtil.serialize(value));
            logger.debug("添加缓存--------"+this.id);
            //getSize();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }

    }

    @Override
    public Object getObject(Object key) {
        Jedis jedis = null;
        Object value = null;
        try {
        	jedis = RedisStandAloneUtil.getJedisPool().getResource();
            value = SerializeUtil.unserialize(jedis.get(getKey(key).getBytes(UTF_8)));
            logger.debug("从缓存中获取-----"+this.id);
            //getSize();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return value;
    }

    @Override
    public Object removeObject(Object key) {
        Jedis jedis = null;
        Object value = null;
        try {
        	jedis = RedisStandAloneUtil.getJedisPool().getResource();
            value = jedis.del(getKey(key).getBytes(UTF_8));
            logger.debug("LRU算法从缓存中移除-----"+this.id);
            //getSize();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
        return value;
    }

    @Override
    public void clear() {
        Jedis jedis = null;
        try {
        	jedis = RedisStandAloneUtil.getJedisPool().getResource();
            Set<byte[]> keys = jedis.keys(getKeys().getBytes(UTF_8));
            logger.debug("出现CUD操作,清空对应Mapper缓存======>"+keys.size());
            for (byte[] key : keys) {
                jedis.del(key);
            }
            //下面是网上流传的方法,极大的降低系统性能,没起到加入缓存应有的作用,这是不可取的。
            //jedis.flushDB();
            //jedis.flushAll();
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {
            if (jedis != null) {
                jedis.close();
            }
        }
    }

    @Override
    public ReadWriteLock getReadWriteLock() {
        return readWriteLock;
    }

}

  

时间: 2024-10-14 12:47:19

真正的mybatis_redis二级缓存的相关文章

[原创]java WEB学习笔记93:Hibernate学习之路---Hibernate 缓存介绍,缓存级别,使用二级缓存的情况,二级缓存的架构集合缓存,二级缓存的并发策略,实现步骤,集合缓存,查询缓存,时间戳缓存

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

SpringMVC mybatis or hibernate ehcache二级缓存maven非和maven版本

获取[下载地址]   QQ: 313596790   [免费支持更新] 支持三大数据库 mysql  oracle  sqlsever   更专业.更强悍.适合不同用户群体 [新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统] A 代码生成器(开发利器);       增删改查的处理类,service层,mybatis的xml,SQL( mysql   和oracle)脚本,   jsp页面 都生成    就不用写搬砖的代码了,生成的放到项目里,可以直接运行 B 阿里巴巴数据库连接

Mybatis一级、二级缓存

一级缓存 首先做一个测试,创建一个mapper配置文件和mapper接口,我这里用了最简单的查询来演示. <mapper namespace="cn.elinzhou.mybatisTest.mapper.UserMapper"> <select id="findUsers" resultType="cn.elinzhou.mybatisTest.pojo.User"> SELECT * FROM user </se

【MyBatis框架】查询缓存-二级缓存原理

二级缓存原理 1.原理 首先看图 首先开启mybatis的二级缓存. sqlSession1去查询用户id为1的用户信息,查询到用户信息会将查询数据存储到二级缓存中. 如果SqlSession3去执行相同 mapper下sql,执行commit提交,清空该 mapper下的二级缓存区域的数据. sqlSession2去查询用户id为1的用户信息,去缓存中找是否存在数据,如果存在直接从缓存中取出数据. 二级缓存与一级缓存区别,二级缓存的范围更大,多个sqlSession可以共享一个UserMapp

[转] Hibernate一级缓存、二级缓存

缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 缓存的介质一般是内存,所以读写速度很快.但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质.缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期. hibernate的缓存包括Session的缓存和SessionFactory的缓

Mybatis源码分析之Cache二级缓存原理 (五)

一:Cache类的介绍 讲解缓存之前我们需要先了解一下Cache接口以及实现MyBatis定义了一个org.apache.ibatis.cache.Cache接口作为其Cache提供者的SPI(ServiceProvider Interface) ,所有的MyBatis内部的Cache缓存,都应该实现这一接口 Cache的实现类中,Cache有不同的功能,每个功能独立,互不影响,则对于不同的Cache功能,这里使用了装饰者模式实现. 看下cache的实现类,如下图: 1.FIFOCache:先进

探索ASP.NET MVC5系列之~~~5.缓存篇(页面缓存+二级缓存)

其实任何资料里面的任何知识点都无所谓,都是不重要的,重要的是学习方法,自行摸索的过程(不妥之处欢迎指正) 汇总:http://www.cnblogs.com/dunitian/p/4822808.html#mvc 本章Demo:https://github.com/dunitian/LoTCodeBase/blob/master/NetCode/6.网页基础/BMVC5/MVC5Base/Controllers/CacheController.cs 这次来篇放松的,咱们不要老是说安全相关的东西.

【企业框架源码】 SpringMVC mybatis or hibernate ehcache二级缓存maven非和maven版本【websocket即时通讯】

获取[下载地址]   [免费支持更新]三大数据库 mysql  oracle  sqlsever   更专业.更强悍.适合不同用户群体[新录针对本系统的视频教程,手把手教开发一个模块,快速掌握本系统] A集成代码生成器 [正反双向(单表.主表.明细表.树形表,开发利器)+快速构建表单;freemaker模版技术 ,0个代码不用写,生成完整的一个模块,带页面.建表sql脚本,处理类,service等完整模块B 集成阿里巴巴数据库连接池druid;  数据库连接池  阿里巴巴的 druid.Drui

hibernate一级缓存和二级缓存的区别

缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事件会同步缓存和物理数据源的数据. 缓存的介质一般是内存,所以读写速度很快.但如果缓存中存放的数据量非常大时,也会用硬盘作为缓存介质.缓存的实现不仅仅要考虑存储的介质,还要考虑到管理缓存的并发访问和缓存数据的生命周期. Hibernate的缓存包括Session的缓存和SessionFactory的缓