mybatis-redis項(xiàng)目分析

redis作為現(xiàn)在最優(yōu)秀的key-value數(shù)據(jù)庫盏浙,非常適合提供項(xiàng)目的緩存服務(wù)系羞。把redis作為mybatis的查詢緩存也是很常見的做法复罐。在網(wǎng)上發(fā)現(xiàn)N多人是自己做的Cache匣掸,其實(shí)在mybatis的git下有一個(gè)子項(xiàng)目mybatis-redis趟紊;這個(gè)項(xiàng)目提供了redis作為mybatis查詢緩存的一個(gè)實(shí)現(xiàn),下面先分析一下這個(gè)項(xiàng)目的實(shí)現(xiàn)原理碰酝,再提出幾個(gè)項(xiàng)目的問題:

代碼實(shí)現(xiàn)

該項(xiàng)目和大家普遍實(shí)現(xiàn)Mybatis的緩存方案大同小異霎匈,無非是實(shí)現(xiàn)Cache接口,并使用jedis操作緩存送爸;不過該項(xiàng)目在設(shè)計(jì)細(xì)節(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啟動的時(shí)候暖释,由MyBatis的CacheBuilder創(chuàng)建,創(chuàng)建的方式很簡單墨吓,就是調(diào)用RedisCache的帶有String參數(shù)的構(gòu)造方法球匕,即RedisCache(String id);而在RedisCache的構(gòu)造方法中帖烘,調(diào)用了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)建的,簡單看下這個(gè)類的主要方法:

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中讀取一個(gè)redis.properties文件:

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

并將該配置文件中的內(nèi)容設(shè)置到RedisConfig對象中役耕,并返回;
接下來聪廉,就是RedisCache使用RedisConfig類創(chuàng)建完成JedisPool瞬痘;
在RedisCache中實(shí)現(xiàn)了一個(gè)簡單的模板方法,用來操作Redis:

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

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

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

接下來看看Cache中最重要的兩個(gè)方法:putObject和getObject图云,通過這兩個(gè)方法來查看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ù)的時(shí)候邻邮,是使用的hash結(jié)構(gòu),把cache的id作為這個(gè)hash的key(cache的id在mybatis中就是mapper的namespace)克婶;這個(gè)mapper中的查詢緩存數(shù)據(jù)作為hash的field筒严,需要緩存的內(nèi)容直接使用SerializeUtil存儲,SerializeUtil和其他的序列化類差不多情萤,負(fù)責(zé)對象的序列化和反序列化鸭蛙;

使用方式

整個(gè)mybatis-redis的關(guān)鍵代碼就這些,通過對代碼的分析筋岛,我們很容易得到mybatis-redis的使用方式:
1娶视,在項(xiàng)目中添加一個(gè)redis.properties配置;
2睁宰,直接在mapper中使用<cache type="org.mybatis.caches.redis.RedisCache" />即可肪获;

分析

通過代碼,我們可以看到在實(shí)際應(yīng)用當(dāng)中可能存在的一些問題:

1.默認(rèn)情況下柒傻,mybatis會為每一個(gè)mapper創(chuàng)建一個(gè)RedisCache孝赫,而JedisPool是在RedisCache的構(gòu)造方法中創(chuàng)建的,這就意味著會為每一個(gè)mapper創(chuàng)建一個(gè)JedisPool红符,使用意圖和開銷上面都會有問題青柄;
2.在很多情況下伐债,我們的應(yīng)用中也會獨(dú)立使用到redis,這樣也無法讓RedisCache直接使用我們項(xiàng)目中可能已經(jīng)存在的JedisPool致开;并且會造成兩個(gè)配置文件(除非我們應(yīng)用也使用redis.properties)峰锁;
3.RedisCache是使用hash來緩存一個(gè)Mapper中的查詢,所以我們只能通過mybatis的cache配置來控制對象的生存時(shí)間双戳,空閑時(shí)間等屬性祖今;而無法獨(dú)立的去配置每一個(gè)緩存區(qū)域(即每一個(gè)hash);

來源:
http://bbs.520it.com/forum.php?mod=viewthread&tid=286&extra=page%3D4

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拣技,一起剝皮案震驚了整個(gè)濱河市千诬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌膏斤,老刑警劉巖徐绑,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異莫辨,居然都是意外死亡傲茄,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門沮榜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盘榨,“玉大人,你說我怎么就攤上這事蟆融〔菅玻” “怎么了?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵型酥,是天一觀的道長山憨。 經(jīng)常有香客問我,道長弥喉,這世上最難降的妖魔是什么郁竟? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮由境,結(jié)果婚禮上棚亩,老公的妹妹穿的比我還像新娘。我一直安慰自己虏杰,他們只是感情好讥蟆,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嘹屯,像睡著了一般攻询。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上州弟,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天钧栖,我揣著相機(jī)與錄音低零,去河邊找鬼。 笑死拯杠,一個(gè)胖子當(dāng)著我的面吹牛掏婶,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播潭陪,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼雄妥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了依溯?” 一聲冷哼從身側(cè)響起老厌,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎黎炉,沒想到半個(gè)月后枝秤,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡慷嗜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年淀弹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庆械。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡薇溃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缭乘,到底是詐尸還是另有隱情沐序,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布忿峻,位于F島的核電站薄啥,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏逛尚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一刁愿、第九天 我趴在偏房一處隱蔽的房頂上張望绰寞。 院中可真熱鬧,春花似錦铣口、人聲如沸滤钱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽件缸。三九已至,卻和暖如春叔遂,著一層夾襖步出監(jiān)牢的瞬間他炊,已是汗流浹背争剿。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留痊末,地道東北人蚕苇。 一個(gè)月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像凿叠,于是被迫代替她去往敵國和親涩笤。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容

  • 【原創(chuàng)文章盒件,轉(zhuǎn)載請注明原文章地址蹬碧,謝謝!】 redis作為現(xiàn)在最優(yōu)秀的key-value數(shù)據(jù)庫炒刁,非常適合提供項(xiàng)目的...
    叩丁狼教育閱讀 5,517評論 1 13
  • 11 MyBatis一級緩存實(shí)現(xiàn)# 11.1 什么是一級緩存锰茉? 為什么使用一級緩存?## 每當(dāng)我們使用MyBati...
    七寸知架構(gòu)閱讀 10,854評論 12 143
  • 1. 簡介 1.1 什么是 MyBatis 切心? MyBatis 是支持定制化 SQL飒筑、存儲過程以及高級映射的優(yōu)秀的...
    笨鳥慢飛閱讀 5,527評論 0 4
  • 前言 主題是Mybatis一級和二級緩存的應(yīng)用及源碼分析。希望在本場chat結(jié)束后绽昏,能夠幫助讀者朋友明白以下三點(diǎn)协屡。...
    余平的余_余平的平閱讀 1,331評論 0 12
  • 一個(gè)群發(fā)的新年祝福讓已經(jīng)快兩年沒聯(lián)系的我們開始了閑聊,也打破了封閉冷凍狀態(tài)全谤。 不要誤會肤晓,我們是朋友,是高中那種很好...
    鷺玲閱讀 246評論 0 0