Mybatis缓存实现

406 阅读3分钟

原文日期:2016-04-22


缓存,第一次接触是在2012年大学看马士兵还是韩顺平的Hibernate的视频的时候。当时听的懵懵懂懂的,但感觉非常高端的样子,估计也是从那时开始就将它定为高端大气上档次的玩意,然后每次面试被问道这玩意的时候就只能呵呵了。。。

最近抱着学习沟通、学习当前新技术的心态去面试了几家公司,发现大伙都在谈论的服务化、微服务、高并发、缓存。通常来说,一般的开发人员在一般开发过程是不会涉及到这些玩意,所以明明知道面试官在扯犊子,但自己却没法答出来,心塞ing。。。回家思考良久,感觉自己还是得静下心来,去重新理清这些高端的问题!!!

今天前任大哥打电话过来,说是我之前的问题已经有思路了,并通知我说需要用缓存机制来实现(老大已经离职创业了去了,还能想到我之前的问题,并且还找了外援处理,点赞,估计这也是大哥牛逼之处吧)。顿时心情激动,这不是我这几天天天被为难的一个东西吗?这次一定要把他理清楚。

之后在网上的找了一篇关于Mybatis和Redis的整合实现,发现挺简单的配置下就好了,然而需要使用Redis服务器,自己又不想去搭建这个东东(即使自己有虚拟机),嫌麻烦。于是就研究起大师的实现思路。这是当时参考的地址blog.csdn.net/fhx007/arti…

经研究发现该类实现了Mybatis的Cache接口。该类中主要创建Redis实例,然后通过该实例将查询出来的数据缓存到Redis服务器上,需要获取的时候直接从Redis服务器上拿即可。

这时一个贱贱的想法在我脑海里萌生出来,我是不是可以直接缓存在本地哈。Redis只是一个缓存的数据源,我完全可以用很多看起来很牛逼的方式来替代他,不就是将数据暂存到一边吗?思路渐渐地就理清了许多,其实只需要一个Map,将需要缓存的数据保存到该Map中即可

package com.sinoservices.sss.utils;

import java.util.HashMap;
import java.util.Map;
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;

/**
 * 使用第三方缓存服务器,处理二级缓存
 * @author Alan
 *
 */
public class MybatisRedisCache implements Cache {

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

    private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();

    private String id;
    private Map<Object, Object> map = new HashMap<Object, Object>();

    public MybatisRedisCache(final String id) {
        if (id == null) {
            throw new IllegalArgumentException("Cache instances require an ID");
        }
        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id=" + id);
        this.id = id;
    }

    @Override
    public String getId() {
        logger.info(">>>>>>>>>>>>>" + id);
        return this.id;
    }

    @Override
    public int getSize() {
        return map.size();
    }

    @Override
    public void putObject(Object key, Object value) {
        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>putObject:" + key + "=" + value);
        map.put(key, value);
        // redisClient.set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value));
    }

    @Override
    public Object getObject(Object key) {
        Object value = map.get(key);
        // Object value = SerializeUtil.unserialize(redisClient.get(SerializeUtil.serialize(key.toString())));
        logger.info(">>>>>>>>>>>>>>>>>>>>>>>>getObject:" + key + "=" + value);
        return value;
    }

    @Override
    public Object removeObject(Object key) {
        return map.remove(key);
        // return redisClient.expire(SerializeUtil.serialize(key.toString()), 0);
    }

    @Override
    public void clear() {
        map.clear();
        // redisClient.flushDB();
    }

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

}

经过以上代码调整,ok,搞定,数据库只会进行一次查询,后面的都是从本地缓存Map中获取

总结:经过这次完结,重新再去看Hibernate或者Mybatis的一级缓存、二级缓存等,似乎瞬间明朗了好多,都是猪鼻子插葱装象。其实你有能力的话,他们都可以是你的菜了。之后再网上又看到了一个类PerpetualCache,这个是Mybatis的默认缓存实现类。仔细膜拜里面的源代码后,才发现它的实现思路和我的基本一致,又一次重复造轮子了,罪恶啊

后记:其实上面的例子只是实现了大概的内容,还是有很多缺陷的。比如每次CUD操作都会清空所有缓存,不过这些都可以控制,具体实现靠自己咯,目前已有些思路,以后有机会再续吧。具体思路参照www.zyiqibook.com/201504/arti…,可实现删除当前Mapper的缓存,不影响其他Mapper缓存使用。