前言
在前一篇博客裏面講了如何實現Mybatis二級緩存的自定義,但是並沒有一個完整的實現,並且還沒有詳解如何使用二級緩存等。這篇文章就來結束這個系列。
選取緩存介質
在這裏的話,我們需要來選取一個合適的緩存介質,對於我們而言,Mybatis的二級緩存是基於namespace的,這也就爲多臺機器共用二級緩存提供了可能性。也正因爲如此,我們不可能將緩存放在本機的內存中,類似於Mybatis官方給的那個HashMap實現的例子是不可能的。當然,Enhance之類的內存緩存也就不可能了。
對此,我們選擇的一個策略是Redis。
自定義二級緩存實現
實際上,首先我們要做的是確定我們將要依賴那些東西,因此,我們需要在此處做的事情就是,確定我們依賴的jar。如下爲我的pom文件。
<dependencies>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.6</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.weimob</groupId>
<artifactId>soa-common</artifactId>
<version>1.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
好了,接下來,讓我們來看代碼的實現。
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import org.apache.ibatis.cache.Cache;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
public class RedisCache implements Cache {
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private String id;
private static ShardedJedisPool pool;
public RedisCache(final String id) {
if (id == null) {
throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
}
private Object execute(RedisCallback callback) {
ShardedJedis jedis = pool.getResource();
try {
return callback.doWithRedis(jedis);
} finally {
jedis.close();
}
}
@Override
public String getId() {
return this.id;
}
@Override
public int getSize() {
return (Integer) execute(new RedisCallback() {
@Override
public Object doWithRedis(ShardedJedis jedis) {
Map<byte[], byte[]> result = jedis.hgetAll(id.toString().getBytes());
return result.size();
}
});
}
@Override
public void putObject(final Object key, final Object value) {
execute(new RedisCallback() {
@Override
public Object doWithRedis(ShardedJedis jedis) {
jedis.hset(id.toString().getBytes(), key.toString().getBytes(), SerializeUtilRedis.serialize(value));
return null;
這裏的話實際上採取了回調,如下爲回調的接口:
public interface RedisCallback {
Object doWithRedis(ShardedJedis jedis);
}
採取這個回調的好處是我們可以讓所有的增刪改查等方法有統一的格式,我們不關注方法自己的實現,但是我們爲他提供了標準。
其中的序列化等操作實際上借用FastJson的就可以完成,在此不是重點。不予以講解。
如何使用
剛纔講的是道,就是如何去實現。現在我們講解的是術。如何做。實際上很簡單,就是在mapper文件中簡單配置下。
<cache type="com.alibaba.com"></cache>
總結
這兩篇文章詳細的講解了如何通過Mybatis爲我們預留的接口擴展它的二級緩存。你可以使用各種各樣的介質。去完成自己的需求。
思考
我們來思考下二級緩存適合使用在什麼地方,事實上,這裏的二級緩存是以namespace爲單位存儲的,這也造成了他有一個致命的缺陷。那就是隻要這個namespace對應的sql發生增刪改等操作,那麼所有的緩存都會被清掉。這也就是說二級緩存適用的範圍就是必須要求查詢大量而別的操作很少的情形。當然,如果這種緩存滿足不了你,那就只能寫到業務代碼裏面了。