mybatis-redis項目分析

【原創(chuàng)文章畔乙,轉載請注明原文章地址叉弦,謝謝!】

redis作為現(xiàn)在最優(yōu)秀的key-value數(shù)據(jù)庫筋岛,非常適合提供項目的緩存服務。把redis作為mybatis的查詢緩存也是很常見的做法睬塌。在網上發(fā)現(xiàn)N多人是自己做的Cache,其實在mybatis的git下有一個子項目mybatis-redis;這個項目提供了redis作為mybatis查詢緩存的一個實現(xiàn)揩晴,下面先分析一下這個項目的實現(xiàn)原理勋陪,再提出幾個項目的問題:

代碼實現(xiàn)##

該項目和大家普遍實現(xiàn)Mybatis的緩存方案大同小異,無非是實現(xiàn)Cache接口硫兰,并使用jedis操作緩存诅愚;不過該項目在設計細節(jié)上有一些區(qū)別;下面簡要分析一下源碼:

public final class RedisCache implements Cache {  
public RedisCache(final String id) {
  if (id == null) {
  throw new IllegalArgumentException("Cache instances require an ID");
}
this.id = id;
RedisConfig redisConfig = RedisConfigurationBuilder.getInstance().parseConfiguration();
pool = new JedisPool(redisConfig, redisConfig.getHost(), redisConfig.getPort(),
        redisConfig.getConnectionTimeout(), redisConfig.getSoTimeout(), redisConfig.getPassword(),
        redisConfig.getDatabase(), redisConfig.getClientName());
}  

RedisCache在mybatis啟動的時候劫映,由MyBatis的CacheBuilder創(chuàng)建违孝,創(chuàng)建的方式很簡單,就是調用RedisCache的帶有String參數(shù)的構造方法泳赋,即RedisCache(String id)雌桑;而在RedisCache的構造方法中,調用了RedisConfigurationBuilder來創(chuàng)建RedisConfig對象祖今,并使用RedisConfig來創(chuàng)建JedisPool校坑。
RedisConfig類繼承了JedisPoolConfig,并提供了host,port等屬性的包裝千诬,簡單看一下RedisConfig的屬性:

public class RedisConfig extends JedisPoolConfig {

private String host = Protocol.DEFAULT_HOST;
private int port = Protocol.DEFAULT_PORT;
private int connectionTimeout = Protocol.DEFAULT_TIMEOUT;
private int soTimeout = Protocol.DEFAULT_TIMEOUT;
private String password;
private int database = Protocol.DEFAULT_DATABASE;
private String clientName;
}

RedisConfig對象是由RedisConfigurationBuilder創(chuàng)建的耍目,簡單看下這個類的主要方法:

public RedisConfig parseConfiguration(ClassLoader classLoader) {
    Properties config = new Properties();

    InputStream input = classLoader.getResourceAsStream(redisPropertiesFilename);
    if (input != null) {
        try {
            config.load(input);
        } catch (IOException e) {
            throw new RuntimeException(
                    "An error occurred while reading classpath property '"
                            + redisPropertiesFilename
                            + "', see nested exceptions", e);
        } finally {
            try {
                input.close();
            } catch (IOException e) {
                // close quietly
            }
        }
    }

    RedisConfig jedisConfig = new RedisConfig();
    setConfigProperties(config, jedisConfig);
    return jedisConfig;
}

核心的方法就是parseConfiguration方法,該方法從classpath中讀取一個redis.properties文件:

host=localhost
port=6379
connectionTimeout=5000
soTimeout=5000
password=
database=0
clientName=

并將該配置文件中的內容設置到RedisConfig對象中徐绑,并返回邪驮;
接下來,就是RedisCache使用RedisConfig類創(chuàng)建完成JedisPool傲茄;
在RedisCache中實現(xiàn)了一個簡單的模板方法毅访,用來操作Redis:

private Object execute(RedisCallback callback) {
Jedis jedis = pool.getResource();
try {
  return callback.doWithRedis(jedis);
} finally {
  jedis.close();
}
}

模板接口為RedisCallback,這個接口中就只需要實現(xiàn)了一個doWithRedis方法而已:

public interface RedisCallback {
    Object doWithRedis(Jedis jedis);
}

接下來看看Cache中最重要的兩個方法:putObject和getObject烫幕,通過這兩個方法來查看mybatis-redis儲存數(shù)據(jù)的格式:

@Override
public void putObject(final Object key, final Object value) {
execute(new RedisCallback() {
  @Override
  public Object doWithRedis(Jedis jedis) {
    jedis.hset(id.toString().getBytes(), key.toString().getBytes(), SerializeUtil.serialize(value));
    return null;
  }
});
}

@Override
public Object getObject(final Object key) {
return execute(new RedisCallback() {
  @Override
  public Object doWithRedis(Jedis jedis) {
    return SerializeUtil.unserialize(jedis.hget(id.toString().getBytes(), key.toString().getBytes()));
  }
});
}

可以很清楚的看到俺抽,mybatis-redis在存儲數(shù)據(jù)的時候,是使用的hash結構较曼,把cache的id作為這個hash的key(cache的id在mybatis中就是mapper的namespace)磷斧;這個mapper中的查詢緩存數(shù)據(jù)作為hash的field,需要緩存的內容直接使用SerializeUtil存儲捷犹,SerializeUtil和其他的序列化類差不多弛饭,負責對象的序列化和反序列化;

使用方式##

整個mybatis-redis的關鍵代碼就這些萍歉,通過對代碼的分析侣颂,我們很容易得到mybatis-redis的使用方式:
1,在項目中添加一個redis.properties配置枪孩;
2憔晒,直接在mapper中使用<cache type="org.mybatis.caches.redis.RedisCache" />即可藻肄;

分析##

通過代碼,我們可以看到在實際應用當中可能存在的一些問題:

  1. 默認情況下拒担,mybatis會為每一個mapper創(chuàng)建一個RedisCache嘹屯,而JedisPool是在RedisCache的構造方法中創(chuàng)建的,這就意味著會為每一個mapper創(chuàng)建一個JedisPool从撼,使用意圖和開銷上面都會有問題州弟;
  2. 在很多情況下,我們的應用中也會獨立使用到redis低零,這樣也無法讓RedisCache直接使用我們項目中可能已經存在的JedisPool婆翔;并且會造成兩個配置文件(除非我們應用也使用redis.properties);
  3. RedisCache是使用hash來緩存一個Mapper中的查詢掏婶,所以我們只能通過mybatis的cache配置來控制對象的生存時間啃奴,空閑時間等屬性;而無法獨立的去配置每一個緩存區(qū)域(即每一個hash)气堕;
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末纺腊,一起剝皮案震驚了整個濱河市溜宽,隨后出現(xiàn)的幾起案子送膳,更是在濱河造成了極大的恐慌,老刑警劉巖姿锭,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件梅桩,死亡現(xiàn)場離奇詭異壹粟,居然都是意外死亡,警方通過查閱死者的電腦和手機宿百,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門趁仙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人垦页,你說我怎么就攤上這事雀费。” “怎么了痊焊?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵盏袄,是天一觀的道長。 經常有香客問我薄啥,道長辕羽,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任垄惧,我火速辦了婚禮刁愿,結果婚禮上,老公的妹妹穿的比我還像新娘到逊。我一直安慰自己铣口,他們只是感情好滤钱,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著脑题,像睡著了一般菩暗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上旭蠕,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天,我揣著相機與錄音旷坦,去河邊找鬼掏熬。 笑死,一個胖子當著我的面吹牛秒梅,可吹牛的內容都是我干的旗芬。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼捆蜀,長吁一口氣:“原來是場噩夢啊……” “哼疮丛!你這毒婦竟也來了?” 一聲冷哼從身側響起辆它,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤誊薄,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后锰茉,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呢蔫,經...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年飒筑,在試婚紗的時候發(fā)現(xiàn)自己被綠了片吊。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡协屡,死狀恐怖俏脊,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情肤晓,我是刑警寧澤爷贫,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站材原,受9級特大地震影響沸久,放射性物質發(fā)生泄漏。R本人自食惡果不足惜余蟹,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一卷胯、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧威酒,春花似錦窑睁、人聲如沸挺峡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽橱赠。三九已至,卻和暖如春箫津,著一層夾襖步出監(jiān)牢的瞬間狭姨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工苏遥, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留饼拍,地道東北人。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓田炭,卻偏偏與公主長得像师抄,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子教硫,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內容