日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

MyBatis学习总结(16)——Mybatis使用的几个建议

發(fā)布時間:2025/3/19 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MyBatis学习总结(16)——Mybatis使用的几个建议 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

2019獨角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

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

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

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

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

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

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

????而且大量的if choose語句,不可避免地,每次生成的SQL會不太一致,會導(dǎo)致ORACLE大量的硬解析,也不可取。?
我們來看看這樣的SQL:?
SELECT * FROM T_NEWS_TEXT WHERE 1 = 1 < choose> < if test ="startdate != null and startdate != '' and enddate != null and endate != ''"> AND PUBLISHTIME >= #{startdate} AND PUBLISHTIME <= #{enddate} </ if> <otherwise> AND PUBLISHTIME >= SYSDATE - 7 AND PUBLISHTIME <= SYSDATE </otherwise></ choose > ????這樣的if判斷,其實是完全沒有必要的,我們可以很簡單的采用DECODE來解決默認(rèn)值問題:?
SELECT * FROM T_NEWS_TEXT WHERE PUBLISHTIME >= DECODE(#{startdate},NULL,SYSDATE-7, #{startdate}) AND PUBLISHTIME <= DECODE(#{enddate},NULL,SYSDATE,#{enddate})

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

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

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

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

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

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

????現(xiàn)在來談?wù)勛⑨屢l(fā)的問題,我做的一個項目中,分頁組件是基于Mybatis的,它會在你寫的SQL腳本外面再套一層SELECT COUNT(*) ROWNUM_ FROM (....) 計算總記錄數(shù),同時有另一個嵌套SELECT * FROM(...) WHERE ROWNUM > 10 AND RONNUM < 10 * 2這種方式生成分頁信息,如果你的腳本中最后一行出現(xiàn)了注釋,則添加的部分會成為注釋的一部分,執(zhí)行就會報錯。除此之外,某些情況下也可能導(dǎo)致部分條件被忽略,如下面的情況:?
SELECT * FROM TEST WHERE COL1 > 1 -- 這里是注釋<if test="a != null and a != ''">AND COL2 = #{a}</if> ????即使傳入的參數(shù)中存在對應(yīng)的參數(shù),實際也不會產(chǎn)生效果,因為后面的內(nèi)容實際上是被完全注釋了。這種錯誤,如果不經(jīng)過嚴(yán)格的測試,是很難發(fā)現(xiàn)的。一般情況下,XML注釋完全可以替代SQL注釋,因此這種行為應(yīng)該可以禁止掉。?

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

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

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

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

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

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

5.簡單使用Mybatis。

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

轉(zhuǎn)載于:https://my.oschina.net/zhanghaiyang/blog/725766

總結(jié)

以上是生活随笔為你收集整理的MyBatis学习总结(16)——Mybatis使用的几个建议的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。