国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|JavaScript|易語(yǔ)言|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - 深入了解MyBatis二級(jí)緩存

深入了解MyBatis二級(jí)緩存

2021-06-24 10:27isea533 Java教程

今天小編就為大家分享一篇關(guān)于深入了解MyBatis二級(jí)緩存,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧

一、創(chuàng)建cache的完整過(guò)程

我們從sqlsessionfactorybuilder解析mybatis-config.xml配置文件開(kāi)始:

?
1
2
reader reader = resources.getresourceasreader("mybatis-config.xml");
sqlsessionfactory sqlsessionfactory = new sqlsessionfactorybuilder().build(reader);

然后是:

?
1
2
xmlconfigbuilder parser = new xmlconfigbuilder(inputstream, environment, properties);
return build(parser.parse());

看parser.parse()方法:

?
1
parseconfiguration(parser.evalnode("/configuration"));

看處理mapper.xml文件的位置:

?
1
mapperelement(root.evalnode("mappers"));

看處理mapper.xml的xmlmapperbuilder:

?
1
2
3
xmlmapperbuilder mapperparser = new xmlmapperbuilder(inputstream, configuration,
   resource, configuration.getsqlfragments());
mapperparser.parse();

繼續(xù)看parse方法:

?
1
configurationelement(parser.evalnode("/mapper"));

到這里:

?
1
2
3
4
5
6
7
string namespace = context.getstringattribute("namespace");
if (namespace.equals("")) {
 throw new builderexception("mapper's namespace cannot be empty");
}
builderassistant.setcurrentnamespace(namespace);
cacherefelement(context.evalnode("cache-ref"));
cacheelement(context.evalnode("cache"));

從這里看到namespace就是xml中<mapper>元素的屬性。然后下面是先后處理的cache-ref和cache,后面的cache會(huì)覆蓋前面的cache-ref,但是如果一開(kāi)始cache-ref沒(méi)有找到引用的cache,他就不會(huì)被覆蓋,會(huì)一直到最后處理完成為止,最后如果存在cache,反而會(huì)被cache-ref覆蓋。這里是不是看著有點(diǎn)暈、有點(diǎn)亂?所以千萬(wàn)別同時(shí)配置這兩個(gè),實(shí)際上也很少有人會(huì)這么做。

看看mybatis如何處理<cache/>:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void cacheelement(xnode context) throws exception {
  if (context != null) {
    string type = context.getstringattribute("type", "perpetual");
    class<? extends cache> typeclass = typealiasregistry.resolvealias(type);
    string eviction = context.getstringattribute("eviction", "lru");
    class<? extends cache> evictionclass = typealiasregistry.resolvealias(eviction);
    long flushinterval = context.getlongattribute("flushinterval");
    integer size = context.getintattribute("size");
    boolean readwrite = !context.getbooleanattribute("readonly", false);
    boolean blocking = context.getbooleanattribute("blocking", false);
    properties props = context.getchildrenasproperties();
    builderassistant.usenewcache(typeclass, evictionclass,
       flushinterval, size, readwrite, blocking, props);
  }
}

從源碼可以看到mybatis讀取了那些屬性,而且很容易可以到這些屬性的默認(rèn)值。

創(chuàng)建java的cache對(duì)象方法為builderassistant.usenewcache,我們看看這段代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public cache usenewcache(class<? extends cache> typeclass,
             class<? extends cache> evictionclass,
             long flushinterval,
             integer size,
             boolean readwrite,
             boolean blocking,
             properties props) {
  typeclass = valueordefault(typeclass, perpetualcache.class);
  evictionclass = valueordefault(evictionclass, lrucache.class);
  cache cache = new cachebuilder(currentnamespace)
      .implementation(typeclass)
      .adddecorator(evictionclass)
      .clearinterval(flushinterval)
      .size(size)
      .readwrite(readwrite)
      .blocking(blocking)
      .properties(props)
      .build();
  configuration.addcache(cache);
  currentcache = cache;
  return cache;
}

從調(diào)用該方法的地方,我們可以看到并沒(méi)有使用返回值cache,在后面的過(guò)程中創(chuàng)建mappedstatement的時(shí)候使用了currentcache。

二、使用cache過(guò)程

在系統(tǒng)中,使用cache的地方在cachingexecutor中:

?
1
2
3
4
5
6
@override
public <e> list<e> query(
    mappedstatement ms, object parameterobject,
    rowbounds rowbounds, resulthandler resulthandler,
    cachekey key, boundsql boundsql) throws sqlexception {
 cache cache = ms.getcache();

獲取cache后,先判斷是否有二級(jí)緩存。

只有通過(guò)<cache/>,<cache-ref/>或@cachenamespace,@cachenamespaceref標(biāo)記使用緩存的mapper.xml或mapper接口(同一個(gè)namespace,不能同時(shí)使用)才會(huì)有二級(jí)緩存。

?
1
if (cache != null) {

如果cache存在,那么會(huì)根據(jù)sql配置(<insert>,<select>,<update>,<delete>的flushcache屬性來(lái)確定是否清空緩存。

?
1
flushcacheifrequired(ms);

然后根據(jù)xml配置的屬性u(píng)secache來(lái)判斷是否使用緩存(resulthandler一般使用的默認(rèn)值,很少會(huì)null)。

?
1
if (ms.isusecache() && resulthandler == null) {

確保方法沒(méi)有out類(lèi)型的參數(shù),mybatis不支持存儲(chǔ)過(guò)程的緩存,所以如果是存儲(chǔ)過(guò)程,這里就會(huì)報(bào)錯(cuò)。

?
1
ensurenooutparams(ms, parameterobject, boundsql);

沒(méi)有問(wèn)題后,就會(huì)從cache中根據(jù)key來(lái)取值:

?
1
2
@suppresswarnings("unchecked")
list<e> list = (list<e>) tcm.getobject(cache, key);

如果沒(méi)有緩存,就會(huì)執(zhí)行查詢(xún),并且將查詢(xún)結(jié)果放到緩存中。

?
1
2
3
4
5
if (list == null) {
 list = delegate.<e>query(ms, parameterobject,
   rowbounds, resulthandler, key, boundsql);
 tcm.putobject(cache, key, list); // issue #578 and #116
}

返回結(jié)果

?
1
2
3
  return list;
 }
}

沒(méi)有緩存時(shí),直接執(zhí)行查詢(xún)

?
1
2
return delegate.<e>query(ms, parameterobject, rowbounds, resulthandler, key, boundsql);
}

在上面的代碼中tcm.putobject(cache, key, list);這句代碼是緩存了結(jié)果。但是實(shí)際上直到sqlsession關(guān)閉,mybatis才以序列化的形式保存到了一個(gè)map(默認(rèn)的緩存配置)中。

三、cache使用時(shí)的注意事項(xiàng)

1. 只能在【只有單表操作】的表上使用緩存

不只是要保證這個(gè)表在整個(gè)系統(tǒng)中只有單表操作,而且和該表有關(guān)的全部操作必須全部在一個(gè)namespace下。

2. 在可以保證查詢(xún)遠(yuǎn)遠(yuǎn)大于insert,update,delete操作的情況下使用緩存

這一點(diǎn)不需要多說(shuō),所有人都應(yīng)該清楚。記住,這一點(diǎn)需要保證在1的前提下才可以!

四、避免使用二級(jí)緩存

可能會(huì)有很多人不理解這里,二級(jí)緩存帶來(lái)的好處遠(yuǎn)遠(yuǎn)比不上他所隱藏的危害。

  • 緩存是以namespace為單位的,不同namespace下的操作互不影響。
  • insert,update,delete操作會(huì)清空所在namespace下的全部緩存。
  • 通常使用mybatis generator生成的代碼中,都是各個(gè)表獨(dú)立的,每個(gè)表都有自己的namespace。

為什么避免使用二級(jí)緩存

在符合【cache使用時(shí)的注意事項(xiàng)】的要求時(shí),并沒(méi)有什么危害。

其他情況就會(huì)有很多危害了。

針對(duì)一個(gè)表的某些操作不在他獨(dú)立的namespace下進(jìn)行。

例如在usermapper.xml中有大多數(shù)針對(duì)user表的操作。但是在一個(gè)xxxmapper.xml中,還有針對(duì)user單表的操作。

這會(huì)導(dǎo)致user在兩個(gè)命名空間下的數(shù)據(jù)不一致。如果在usermapper.xml中做了刷新緩存的操作,在xxxmapper.xml中緩存仍然有效,如果有針對(duì)user的單表查詢(xún),使用緩存的結(jié)果可能會(huì)不正確。

更危險(xiǎn)的情況是在xxxmapper.xml做了insert,update,delete操作時(shí),會(huì)導(dǎo)致usermapper.xml中的各種操作充滿(mǎn)未知和風(fēng)險(xiǎn)。

有關(guān)這樣單表的操作可能不常見(jiàn)。但是你也許想到了一種常見(jiàn)的情況。

多表操作一定不能使用緩存

為什么不能?

首先不管多表操作寫(xiě)到那個(gè)namespace下,都會(huì)存在某個(gè)表不在這個(gè)namespace下的情況。

例如兩個(gè)表:role和user_role,如果我想查詢(xún)出某個(gè)用戶(hù)的全部角色role,就一定會(huì)涉及到多表的操作。

?
1
2
3
<select id="selectuserroles" resulttype="userrolevo">
 select * from user_role a,role b where a.roleid = b.roleid and a.userid = #{userid}
</select>

像上面這個(gè)查詢(xún),你會(huì)寫(xiě)到那個(gè)xml中呢??

不管是寫(xiě)到rolemapper.xml還是userrolemapper.xml,或者是一個(gè)獨(dú)立的xxxmapper.xml中。如果使用了二級(jí)緩存,都會(huì)導(dǎo)致上面這個(gè)查詢(xún)結(jié)果可能不正確。

如果你正好修改了這個(gè)用戶(hù)的角色,上面這個(gè)查詢(xún)使用緩存的時(shí)候結(jié)果就是錯(cuò)的。

這點(diǎn)應(yīng)該很容易理解。

在我看來(lái),就以mybatis目前的緩存方式來(lái)看是無(wú)解的。多表操作根本不能緩存。

如果你讓他們都使用同一個(gè)namespace(通過(guò)<cache-ref>)來(lái)避免臟數(shù)據(jù),那就失去了緩存的意義。

看到這里,實(shí)際上就是說(shuō),二級(jí)緩存不能用。整篇文章介紹這么多也沒(méi)什么用了。

五、挽救二級(jí)緩存?

想更高效率的使用二級(jí)緩存是解決不了了。

但是解決多表操作避免臟數(shù)據(jù)還是有法解決的。解決思路就是通過(guò)攔截器判斷執(zhí)行的sql涉及到那些表(可以用jsqlparser解析),然后把相關(guān)表的緩存自動(dòng)清空。但是這種方式對(duì)緩存的使用效率是很低的。

設(shè)計(jì)這樣一個(gè)插件是相當(dāng)復(fù)雜的,既然我沒(méi)想著去實(shí)現(xiàn),就不廢話(huà)了。

最后還是建議,放棄二級(jí)緩存,在業(yè)務(wù)層使用可控制的緩存代替更好。

推薦:集成 spring redis 緩存
http://www.jfrwli.cn/article/173078.html

總結(jié)

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,謝謝大家對(duì)服務(wù)器之家的支持。如果你想了解更多相關(guān)內(nèi)容請(qǐng)查看下面相關(guān)鏈接

原文鏈接:https://blog.csdn.net/isea533/article/details/44566257

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 欧美一区二区三区精品 | 欧美一级片在线播放 | 亚洲第一色 | 久久久精彩 | 国产精品久久久久久久一区探花 | 日韩精品一二三区 | 亚洲精品久久久久久一区二区 | 国产日韩欧美三级 | 色综合网在线 | 欧美综合第一页 | 欧美中文字幕一区 | 综合色导航 | www久| 久久综合另类激情人妖 | 精品一区二区免费视频视频 | 99国产一区 | 中文字幕亚洲欧美日韩在线不卡 | 亚洲午夜精品一区二区三区 | 欧美一级片在线播放 | 午夜久久久 | 免费观看一级毛片 | the蜜臀av入口| 欧美日韩国产影院 | 在线播放视频一区二区 | 99久久视频 | 91精品一久久香蕉国产线看观看新通道出现 | 国产日韩精品入口 | 另类在线 | 久久激情久久 | 日韩高清一区 | 午夜国产影院 | 国内精品久久久久久中文字幕 | 在线二区 | 在线二区 | 日韩欧美在线观看一区二区三区 | 福利视频在线播放 | 91 在线观看 | 玖玖操 | 亚洲激情在线视频 | 国产精品免费网站 | 日韩欧美一级 |