之前的文章中我們意見分析了一級緩存、二級緩存的相關源碼和基本原理,今天我們來分享下了mybatis二級緩存和redis的結合,當然mybatis二級緩存也可以和ehcache、memcache、OSCache、Hazelcast結合使用。二級緩存相關的源碼分享請參考《Mybatis源碼分析之Cache二級緩存原理》。我們通過兩種方式來實戰,一種是自己編寫緩存、另外一種是官方給出的demo地址:http://www.mybatis.org/redis-cache/
一:自定義mybatis緩存
我們知道任何mybatis二級緩存都需要實現一個接口,這個接口就是org.apache.ibatis.cache.Cache,代碼如下:
package com.demo.spring.mybatis.cache;
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 com.demo.spring.mybatis.util.SerializeUtil;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
public class MybatisRedisCache implements Cache {
private static Logger logger = LoggerFactory.getLogger(MybatisRedisCache.class);
private Jedis redisClient = createReids();
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private String id;
public MybatisRedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>MybatisRedisCache:id=" + id);
this.id = id;
}
@Override
public String getId() {
return this.id;
}
@Override
public int getSize() {
return Integer.valueOf(redisClient.dbSize().toString());
}
@Override
public void putObject(Object key, Object value) {
logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>putObject:" + key + "=" + value);
redisClient.set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value));
}
@Override
public Object getObject(Object key) {
Object value = SerializeUtil.unserialize(redisClient.get(SerializeUtil.serialize(key.toString())));
logger.debug(">>>>>>>>>>>>>>>>>>>>>>>>getObject:" + key + "=" + value);
return value;
}
@Override
public Object removeObject(Object key) {
return redisClient.expire(SerializeUtil.serialize(key.toString()), 0);
}
@Override
public void clear() {
redisClient.flushDB();
}
@Override
public ReadWriteLock getReadWriteLock() {
return readWriteLock;
}
protected static Jedis createReids() {
JedisPool pool = new JedisPool("127.0.0.1", 6379);
return pool.getResource();
}
}
以上代碼很簡單就是基本的Cache實現,在定義一個序列化的工具類
package com.demo.spring.mybatis.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SerializeUtil {
public static byte[] serialize(Object object) {
ObjectOutputStream oos = null;
ByteArrayOutputStream baos = null;
try {
// 序列化
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
oos.writeObject(object);
byte[] bytes = baos.toByteArray();
return bytes;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static Object unserialize(byte[] bytes) {
ByteArrayInputStream bais = null;
try {
// 反序列化
bais = new ByteArrayInputStream(bytes);
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
}
return null;
}
}
然后在mapper.xml配置
<cache eviction="LRU" type="com.demo.spring.mybatis.cache.MybatisRedisCache"/>
當然在主配置文件里面還需要配置如下代碼,代表開啟二級緩存,默認是不開啟的
<setting name="cacheEnabled" value="true" />
所以得配置和代碼都已經完成了運行結果如下:

為什么第二次走的是一級緩存呢?
這個在講二級緩存源碼的時候分析過,只有當執行commit的時候才把之前查詢的結果放入緩存。
打開嗎redis查看如下,因為存入的是序列化的結果,不過我們隱約還是能看到一些信息到下圖

二:官方的實例
地址: http://www.mybatis.org/redis-cache/
其實和我們自定義的差不多的,不過使用的時候需要注意redis客戶端版本要和它的版本兼容,否則或報錯。
mybatis-redis 1.0.0-beta2 對應負redis.clients » jedis 2.8.0 目前的最高版本2.9.0不支持
