一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

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

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - Mybatis學(xué)習(xí)總結(jié)之mybatis使用建議

Mybatis學(xué)習(xí)總結(jié)之mybatis使用建議

2020-05-04 14:23一杯甜酒 JAVA教程

這篇文章主要介紹了Mybatis學(xué)習(xí)總結(jié)之mybatis使用建議的相關(guān)資料,非常具有參考借鑒價(jià)值,需要的朋友可以參考下

簡介:什么是MyBatis?

(前身為iBatis) MyBatis 是一個(gè)可以自定義SQL、存儲(chǔ)過程和高級(jí)映射的持久層框架。MyBatis消除了幾乎所有的JDBC代碼和參數(shù)的手工設(shè)置以及對(duì)結(jié)果集的檢索。MyBatis可以使用簡單的XML或注解用于配置和原始映射,將接口和Java的POJO(Plain Old Java Objects,普通的Java對(duì)象)映射成數(shù)據(jù)庫中的記錄。

1.Mapper層參數(shù)為Map,由Service層負(fù)責(zé)重載。

    Mapper由于機(jī)制的問題,不能重載,參數(shù)一般設(shè)置成Map,但這樣會(huì)使參數(shù)變得模糊,如果想要使代碼變得清晰,可以通過service層來實(shí)現(xiàn)重載的目的,對(duì)外提供的Service層是重載的,但這些重載的Service方法其實(shí)是調(diào)同一個(gè)Mapper,只不過相應(yīng)的參數(shù)并不一致。

    也許有人會(huì)想,為什么不在Service層也設(shè)置成Map呢?我個(gè)人是不推薦這么做的,雖然為了方便,我在之前的項(xiàng)目中也大量采用了這種方式,但很明顯會(huì)給日后的維護(hù)工作帶來麻煩。因?yàn)檫@么做會(huì)使你整個(gè)MVC都依賴于Map模型,這個(gè)模型其實(shí)是很不錯(cuò)的,方便搭框架,但存在一個(gè)問題:僅僅看方法簽名,你不清楚Map中所擁有的參數(shù)個(gè)數(shù)、類型、每個(gè)參數(shù)代表的含義。

    試想,你只對(duì)Service層變更,或者DAO層變更,你需要清楚整個(gè)流程中Map傳遞過來的參數(shù),除非你注釋或者文檔良好,否則必須把每一層的代碼都了解清楚,你才知道傳遞了哪些參數(shù)。針對(duì)于簡單MVC,那倒也還好,但如果層次復(fù)雜之后,代碼會(huì)變得異常復(fù)雜,而且如果我增加一個(gè)參數(shù),需要把每一個(gè)層的注釋都添加上。相對(duì)于注釋,使用方法簽名來保證這種代碼可控性會(huì)來得更可行一些,因?yàn)樽⑨層锌赡苁沁^時(shí)的,但方法簽名一般不太可能是陳舊的。

2.盡量少用if choose等語句,降低維護(hù)的難度。

    Mybatis的配置SQL時(shí),盡量少用if choose 等標(biāo)簽,能用SQL實(shí)現(xiàn)判斷的盡量用SQL來判斷(CASE WHEN ,DECODE等),以便后期維護(hù)。否則,一旦SQL膨脹,超級(jí)惡心,如果需要調(diào)試Mybatis中的SQL,需要去除大量的判斷語句,非常麻煩。另一方面,大量的if判斷,會(huì)使生成的SQL中包含大量的空格,增加網(wǎng)絡(luò)傳輸?shù)臅r(shí)間,也不可取。

    而且大量的if choose語句,不可避免地,每次生成的SQL會(huì)不太一致,會(huì)導(dǎo)致ORACLE大量的硬解析,也不可取。

我們來看看這樣的SQL:

?
1
2
3
4
5
6
7
8
<code class="hljs sql" style="padding:0.5em; margin:0px; display:block; color:rgb(101,123,131); overflow-x:auto; background:rgb(253,246,227)"><span class="hljs-operator" style="padding:0px; margin:0px"><span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">SELECT</span> * <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">FROM</span> T_NEWS_TEXT <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">WHERE</span> <span class="hljs-number" style="padding:0px; margin:0px; color:rgb(42,161,152)">1</span> = <span class="hljs-number" style="padding:0px; margin:0px; color:rgb(42,161,152)">1</span>
< <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">choose</span>>
< <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">if</span> test =<span class="hljs-string" style="padding:0px; margin:0px; color:rgb(42,161,152)">"startdate != null and startdate != '' and enddate != null and endate != ''"</span>>
<span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">AND</span> PUBLISHTIME >= #{startdate} <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">AND</span> PUBLISHTIME <= #{enddate}
</ <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">if</span>>
<otherwise>
<span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">AND</span> PUBLISHTIME >= <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">SYSDATE</span> - <span class="hljs-number" style="padding:0px; margin:0px; color:rgb(42,161,152)">7</span> <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">AND</span> PUBLISHTIME <= <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">SYSDATE</span>
</otherwise></ <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">choose</span> ></span>

這樣的if判斷,其實(shí)是完全沒有必要的,我們可以很簡單的采用DECODE來解決默認(rèn)值問題:

?
1
<code class="hljs sql" style="padding:0.5em; margin:0px; display:block; color:rgb(101,123,131); overflow-x:auto; background:rgb(253,246,227)"><span class="hljs-operator" style="padding:0px; margin:0px"><span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">SELECT</span> * <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">FROM</span> T_NEWS_TEXT <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">WHERE</span> PUBLISHTIME >= <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">DECODE</span>(#{startdate},<span class="hljs-literal" style="padding:0px; margin:0px">NULL</span>,<span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">SYSDATE</span>-<span class="hljs-number" style="padding:0px; margin:0px; color:rgb(42,161,152)">7</span>, #{startdate}) <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">AND</span> PUBLISHTIME <= <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">DECODE</span>(#{enddate},<span class="hljs-literal" style="padding:0px; margin:0px">NULL</span>,<span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">SYSDATE</span>,#{enddate})</span></code>

    當(dāng)然有人會(huì)想,引入CASE WHEN,DECODE會(huì)導(dǎo)致需要ORACLE函數(shù)解析,會(huì)拖慢SQL執(zhí)行時(shí)間,有興趣的同學(xué)可以回去做一下測試,看看是否會(huì)有大的影響。就個(gè)人經(jīng)驗(yàn)而言,在我的開發(fā)過程,沒有發(fā)現(xiàn)因?yàn)楹瘮?shù)解析導(dǎo)致SQL變慢的情形。影響SQL執(zhí)行效率的一般情況下是JOIN、ORDER BY、DISTINCT、PARTITATION BY等這些操作,這些操作一般與表結(jié)構(gòu)設(shè)計(jì)有很大的關(guān)聯(lián)。相對(duì)于這些的效率影響程度,函數(shù)解析對(duì)于SQL執(zhí)行速度影響應(yīng)該是可以忽略不計(jì)的。

    另外一點(diǎn),對(duì)于一些默認(rèn)值的賦值,像上面那條SQL,默認(rèn)成當(dāng)前日期什么的,其實(shí)可以完全提到Service層或Controller層做處理,在Mybatis中應(yīng)該要少用這些判斷。因?yàn)椋@樣的話,很難做緩存處理。如果startdate為空,在SQL上使用動(dòng)態(tài)的SYSDATE,就無法確定緩存startdate日期的key應(yīng)該是什么了。所以參數(shù)最好在傳遞至Mybatis之前都處理好,這樣Mybatis層也能減少部分if choose語句,同時(shí)也方便做緩存處理。

    當(dāng)然不使用if choose也并不是絕對(duì)的,有時(shí)候?yàn)榱藘?yōu)化SQL,不得不使用if來解決,比如說LIKE語句,當(dāng)然一般不推薦使用LIKE,但如果存在使用的場景,盡可能在不需要使用時(shí)候去除LIKE,比如查詢文章標(biāo)題,以提高查詢效率。 最好的方式是使用lucence等搜索引擎來解決這種全文索引的問題。

    總的來說,if與choose判斷分支是不可能完全去除的,但是推薦使用SQL原生的方式來解決一些動(dòng)態(tài)問題,而不應(yīng)該完全依賴Mybatis來完成動(dòng)態(tài)分支的判斷,因?yàn)榕袛喾种н^于復(fù)雜,而且難以維護(hù)。

3.用XML注釋取代SQL注釋。

    Mybatis中原SQL的注釋盡量不要保留,注釋會(huì)引發(fā)一些問題,如果需要使用注釋,可以在XML中用<!-- -->來注釋,保證在生成的SQL中不會(huì)存在SQL注釋,從而降低問題出現(xiàn)的可能性。這樣做還有一個(gè)好處,就是在IDE中可以很清楚的區(qū)分注釋與SQL。

    現(xiàn)在來談?wù)勛⑨屢l(fā)的問題,我做的一個(gè)項(xiàng)目中,分頁組件是基于Mybatis的,它會(huì)在你寫的SQL腳本外面再套一層SELECT COUNT(*) ROWNUM_ FROM (....) 計(jì)算總記錄數(shù),同時(shí)有另一個(gè)嵌套SELECT * FROM(...) WHERE ROWNUM > 10 AND RONNUM < 10 * 2這種方式生成分頁信息,如果你的腳本中最后一行出現(xiàn)了注釋,則添加的部分會(huì)成為注釋的一部分,執(zhí)行就會(huì)報(bào)錯(cuò)。除此之外,某些情況下也可能導(dǎo)致部分條件被忽略,如下面的情況:

?
1
<code class="hljs vbnet" style="padding:0.5em; margin:0px; display:block; color:rgb(101,123,131); overflow-x:auto; background:rgb(253,246,227)"><span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">SELECT</span> * <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">FROM</span> TEST <span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">WHERE</span> COL1 > <span class="hljs-number" style="padding:0px; margin:0px; color:rgb(42,161,152)">1</span> -- 這里是注釋<<span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">if</span> test=<span class="hljs-string" style="padding:0px; margin:0px; color:rgb(42,161,152)">"a != null and a != ''"</span>><span class="hljs-keyword" style="padding:0px; margin:0px; color:rgb(133,153,0)">AND</span> COL2 = <span class="hljs-preprocessor" style="padding:0px; margin:0px; color:rgb(203,75,22)">#{a}</<span class="hljs-keyword" style="padding:0px; margin:0px">if</span>></span></code>

    即使傳入的參數(shù)中存在對(duì)應(yīng)的參數(shù),實(shí)際也不會(huì)產(chǎn)生效果,因?yàn)楹竺娴膬?nèi)容實(shí)際上是被完全注釋了。這種錯(cuò)誤,如果不經(jīng)過嚴(yán)格的測試,是很難發(fā)現(xiàn)的。一般情況下,XML注釋完全可以替代SQL注釋,因此這種行為應(yīng)該可以禁止掉。

4.盡可能使用#{},而不是${}.

    Mybatis中盡量不要使用${},盡量這樣做很方便開發(fā),但是有一個(gè)問題,就是大量使用會(huì)導(dǎo)致ORACLE的硬解析,拖慢數(shù)據(jù)庫性能,運(yùn)行越久,數(shù)據(jù)庫性能會(huì)越差。對(duì)于一般多個(gè)字符串IN的處理,可以參考如下的解決方案:http://www.myexception.cn/sql/849573.html,基本可以解決大部分${}.

    關(guān)于${},另一個(gè)誤用的地方就是LIKE,我這邊還有個(gè)案例:比如一些樹型菜單,節(jié)點(diǎn)會(huì)設(shè)計(jì)成'01','0101',用兩位節(jié)點(diǎn)來區(qū)分層級(jí),這時(shí)候,如果需要查詢01節(jié)點(diǎn)下所有的節(jié)點(diǎn),最簡單的SQL便是:SELECT * FROM TREE WHERE ID LIKE '01%',這種SQL其實(shí)無可厚非,因?yàn)樗材苡玫剿饕圆恍枰貏e的處理,直接使用就行了。但如果是文章標(biāo)題,則需要額外注意了:SELECT * FROM T_NEWS_TEXT WHERE TITLE LIKE '%OSC%',這是怎么也不會(huì)用到索引的,上面說了,最好采用全文檢索。但如果離不開LIKE,就需要注意使用的方式: ID LIKE #{ID} || '%'而不是ID LIKE '${ID}%',減少硬解析的可能。

    有人覺得使用||會(huì)增加ORACLE處理的時(shí)間,我覺得不要把ORACLE看得太傻,雖然有時(shí)候確實(shí)非常傻,有空可以再總結(jié)ORACLE傻不垃圾的地方,但是稍加測試便知:這種串聯(lián)方式,對(duì)于整個(gè)SQL的解析執(zhí)行,應(yīng)該是微乎其微的。

    當(dāng)然還有一些特殊情況是沒有辦法處理的,比如說動(dòng)態(tài)注入列名、表名等。對(duì)于這些情況,則比較棘手,沒有找到比較方便的手段。由于這種情況出現(xiàn)的可能性會(huì)比較少,所以使用${}倒也不至于有什么太大的影響。當(dāng)然你如果有代碼潔癖的話,可以使用ORACLE的動(dòng)態(tài)執(zhí)行SQL的機(jī)制Execute immediate,這樣就可以完全避免${}出現(xiàn)的可能性了。這樣會(huì)引入比較復(fù)雜的模型,這個(gè)時(shí)候,你就需要取舍了。

    針對(duì)于以上動(dòng)態(tài)SQL所導(dǎo)致的問題,最激進(jìn)的方式是全部采用存儲(chǔ)過程,用數(shù)據(jù)庫原生的方式來解決,方便開發(fā)調(diào)試,當(dāng)然也會(huì)帶來問題:對(duì)開發(fā)人員會(huì)有更高的要求、存儲(chǔ)過程的管理等等,我這邊項(xiàng)目沒有采用過這種方式,這里不做更多的展開。

5.簡單使用Mybatis。

    Mybatis的功能相對(duì)而言還是比較弱的,缺少了好多必要的輔助庫,字符串處理等等,擴(kuò)展也比較困難,一般也就可能對(duì)返回值進(jìn)行一些處理。因此最好僅僅把它作為單純的SQL配置文件,以及簡單的ORM框架。不要嘗試在Mybatis中做過多的動(dòng)態(tài)SQL,否則會(huì)導(dǎo)致后續(xù)的維護(hù)非常惡心。

以上所述是小編給大家介紹的Mybatis學(xué)習(xí)總結(jié)之mybatis使用建議,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)服務(wù)器之家網(wǎng)站的支持!

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 娇喘嗯嗯 轻点啊视频福利 九九九九在线精品免费视频 | 青青草99久久精品国产综合 | 欧美破苞合集 magnet | 海派甜心完整版在线观看 | 爸爸的宝贝小说全文在线阅读 | 久久视频这只精品99re6 | 国产成人精品免费视频大全五级 | 色久久一个亚洲综合网 | 亚洲欧美乱 | 国产精品怡红院在线观看 | 青草福利在线 | 成人精品一区二区三区中文字幕 | 欧美日韩亚洲综合在线一区二区 | 国产精品自产拍在线观看2019 | 狠狠色综合久久久久尤物 | 亚洲欧美日韩综合在线播放 | 国产精品嫩草影院一二三区 | 四虎精品免费国产成人 | 视频大全在线观看免费 | 九九精品视频在线观看 | 国产小视频免费看 | 国产成人a v在线影院 | 97色| 222aaa精品影院 | 日本日日黄| 四虎最新永久免费网址 | 五月最新女厕所高跟嘘嘘 | 久久精品热只有精品 | 99久久国产综合精品麻豆 | 色综合久久六月婷婷中文字幕 | eee在线播放成人免费 | 男女做受快插大片 | 91精品国产综合久久消防器材 | 亚洲国产午夜看片 | 午夜片神马影院福利 | 国产一区国产二区国产三区 | 欧美福利在线播放 | 好奇害死猫在线观看 | 女人肮脏的交易中文字幕未删减版 | 成人欧美一区在线视频在线观看 | 欧美美女被艹 |