Mybatis學習中的高頻問題總結(jié)_第1頁
Mybatis學習中的高頻問題總結(jié)_第2頁
Mybatis學習中的高頻問題總結(jié)_第3頁
Mybatis學習中的高頻問題總結(jié)_第4頁
Mybatis學習中的高頻問題總結(jié)_第5頁
已閱讀5頁,還剩10頁未讀 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

案例一:

數(shù)據(jù)庫表使用了聯(lián)合主鍵,逆向生成的時候生成了兩個實體類??雌饋韯e扭。

但還是可以用。后來就先取消主鍵,生成完后再將主鍵加上。還有就是,tinyint

本來以為用來表示比較小的整數(shù),結(jié)果生成了布爾型的屬性。后來就表示是和

否才用tinyint了。逆向生成的sql語句絕對不能人為改動,否則再次生成的

時候會重復生成。但遑,盡管踩過坑,我還是覺得mybatis超級好用,比

hibernate好多了。雖然hibernate我只試過一點之后就完全轉(zhuǎn)向了mybatis

To

案例二:

sum()和count。使用場景不對導致出錯:

count。、count。)、count(O)就是指絕對的行數(shù),哪怕某行所有字段全部為

null也會計算在內(nèi)。count⑴和count。相比Jnnodb來說count(*)效率低。

如果count(列名)查詢出來的結(jié)果就是查出列名中不為null的行數(shù);

sum(列名)對指定列名進行求和

MyBatis把int類型的0處理成空串''和mysql處理空串''為0的問題,在

Mybatis的hopper中整數(shù)類型條件該如何判斷?

當數(shù)據(jù)庫字段類型是整數(shù),如果參數(shù)變量為空字符串或者NULL,Mybatis會

自動將參數(shù)賦值0,所以如果要判斷整數(shù)參數(shù)的多種狀態(tài)在傳遞數(shù)值到

Mapper之前就要判斷是否為空字符串和NULL并將相應的狀態(tài)數(shù)值賦值給該

參數(shù),否則參數(shù)值等于空字符串、NULL和0得到的結(jié)果是一樣的。

一般情況下,涉及到int類型的操作的時候,在Service中會統(tǒng)一把數(shù)字類型

先變成字符串類型,然后再傳遞到Mapper中操作。

時間戳的使用

在創(chuàng)建新記錄的時候把這個字段設置為當前時間,但以后修改時,不再刷新它

(可以給createtime使用這個):

TIMESTAMPDEFAULTCURRENT_TIMESTAMP

在創(chuàng)建新記錄和修改現(xiàn)有記錄的時候都對這個數(shù)據(jù)列刷新(可以給update使

用這個):

TIMESTAMPDEFAULTCURRENT_TIMESTAMPONUPDATE

CURRENT_TIMESTAMP

在使用resultMap的時候,要把ID寫在第一行,否則的話,就會報錯。

案例三:

XML轉(zhuǎn)義字符,如果直接寫就會報錯,需要用左邊一列的轉(zhuǎn)義字符

?<<小于號

?>>大于號

?&&和

?"單引號

?…雙引號

案例四:

前幾天在項目中碰到來說下吧。大神可繞道。在使用selectOne查詢個數(shù)時,

如果你寫了resultType為Integer然后在業(yè)務代碼中很自然的用一個變量int

去接當前這個方法的返回,如果按照你傳入的條件在數(shù)據(jù)庫中沒有找到相關的

值,止匕時selectOne方法的返回值會是一個null,當你使用Java的自動訴箱

機制的時候會報出一個無情的NPE。

原因:Java在自動拆箱的時候會調(diào)用Integer類中的intValue方法,如果當

前對象為則拋出

null,NPEW

因此,在接受的時候要判空,否則可能異常。

案例五:

多參數(shù)的使用

MyBatis的查詢或者更新中,如果需要多個參數(shù)有如下幾種辦法:

?對象映射,建立一個Java對象,并作為接口的參數(shù),對象的屬性可以

直接使用#{屬性名}的方式訪問;

?Map,參數(shù)為一個Map,key對于屬性名,value對于參數(shù)值,這個方

法就是傳參數(shù)是需要建立一個Map的臨時對象;

?@param參數(shù)注解,在接口方法參數(shù)前加入?yún)?shù)名稱注解,這樣就可以

直接在Mapper中通過參數(shù)名訪問;

?通過序號訪問,第一個參數(shù)#{0}或#223011},第二個參數(shù)#{1},

#{param2}

MyBatis中時間字段的使用-返回

時間字段的返回目前筆者采用放回字符串的方式:

date_format(update_time,,%Y-%c-%d%H:%i:%s')updatetime

采用MySQL的時間格式化方法。

或者放回Timestamp類型的數(shù)據(jù),要求放回對象屬性參數(shù)為Timestamp.

MyBatis中時間字段的使用-參數(shù)

如果需要查詢一段時間范圍的數(shù)據(jù)時,可以通過以下動態(tài)SQL的方式查詢數(shù)

據(jù):

andIbr.update_time>#{startTime}

andlbr.update_time<#{endTime,javaType=Date>jdbcType=TIMESTAMP}

對于的接口方法名稱如下:

...DatestartTime^DateendTime...

我想這個方法會比通過格式轉(zhuǎn)換的效率要高一些

MyBatis中時間字段的使用-寫入

寫入可是直接寫入Timestamp的數(shù)據(jù),需要描述一些寫入的jdbcType,如

下:

{installTime,jdbcType=TIMESTAMP)

Mapper?層參數(shù)為Map,由Service層負責重載,

Mapper由于機制的問題,不能重載,參數(shù)一般設置成Map,但這樣會使參

數(shù)變得模糊,如果想要使代碼變得清晰,可以通過service層來實現(xiàn)重載的目

的,對外提供的Service層是重載的,但這些重載的Service方法其實是調(diào)同

一個Mapper,只不過相應的參數(shù)并不一致。

也許有人會想,為什么不在Service層也設置成M叩呢?我個人是不推薦這

么做的,雖然為了方便,我在之前的項目中也大量采用了這種方式,但很明顯

會給日后的維護工作帶來麻煩。因為這么做會使你整個MVC都依賴于Map

模型,這個模型其實是很不錯的,方便搭框架,但存在一個問題:僅僅看方法

簽名,你不清楚Map中所擁有的參數(shù)個數(shù)、類型、每個參數(shù)代表的含義。

試想,你只對Service層變更,或者DAO層變更,你需要清楚整個流程中

Map傳遞過來的參數(shù),除非你注釋或者文檔良好,否則必須把每一層的代碼

都了解清楚,你才知道傳遞了哪些參數(shù)。針對于簡單MVC,那倒也還好,但

如果層次復雜之后,代碼會變得異常復雜,而且如果我增加一個參數(shù),需要把

每一個層的注釋都添加上。相對于注釋,使用方法簽名來保證這種代碼可斐性

會來得更可行一些,因為注釋有可能是過時的,但方法簽名一般不太可能是陳

舊的。

盡量少用ifchoose等語句,降低維護的難度。

Mybatis的配置SQL時,盡量少用ifchoose等標簽,能用SQL實現(xiàn)判斷的

盡量用SQL來判斷(CASEWHEN.DECODE等),以便后期維護。否則,一旦

SQL膨脹,超級惡心,如果需要調(diào)試Mybatis中的SQL,需要去除大量的判

斷語句,非常麻煩.另一方面,大量的if判斷,會使生成的SQL中包含大量

的空格,增加網(wǎng)絡傳輸?shù)臅r間,也不可取。

而且大量的ifchoose語句,不可避免地,每次生成的SQL會不太一致,會導

致ORACLE大量的硬解析,也不可取。

我們來看看這樣的SQL:

這樣的if判斷,其實是完全沒有必要的,我們可以很簡單的采用DECODE來解

決默認值問題:

當然有人會想,引入CASEWHEN,DECODE會導致需要ORACLE函數(shù)解析,

會拖慢SQL執(zhí)行時間,有興趣的同學可以回去做一下測試,看看是否會有大

的影響。就個人經(jīng)驗而言,在我的開發(fā)過程,沒有發(fā)現(xiàn)因為函數(shù)解析導致SQL

變慢的情形。影響SQL執(zhí)行效率的一般情況下是JOIN、ORDERBY、DISTINCT、

PARTITATIONBY等這些操作,這些操作一般與表結(jié)構(gòu)設計有很大的關聯(lián)。

相對于這些的效率影響程度,函數(shù)解析對于SQL執(zhí)行速度影響應該是可以忽

略不計的。

另外一點對于一些默認值的賦值,像上面那條SQL,默認成當前日期什么的,

其實可以完全提到Service層或Controller層做處理,在Mybatis中應該要

少用這些判斷。因為,這樣的話,很難做緩存處理。如果startdate為空,在

SQL上使用動態(tài)的SYSDATE,就無法確定緩存startdate日期的key應該是

什么了。所以參數(shù)最好在傳遞至Mybatis之前都處理好,這樣Mybatis層也

能減少部分ifchoose語句,同時也方便做緩存處理。

當然不使用ifchoose也并不是絕對的,有時候為了優(yōu)化SQL,不得不使用if

來解決,比如說LIKE語句,當然一般不推薦使用LIKE,但如果存在使用的場

景盡可能在不需要使用時候去除LIKE比如查詢文章標題以提高查詢效率。

最好的方式是使用lucence等搜索引擎來解決這種全文索引的問題。

總的來說,if與choose判斷分支是不可能完全去除的,但是推薦使用SQL

原生的方式來解決一些動態(tài)問題,而不應該完全依賴Mybatis來完成動態(tài)分

支的判斷,因為判斷分支過于復雜,而且難以維護。

用XML注釋取代SQL注釋。

Mybatis中原SQL的注釋盡量不要保留,注釋會引發(fā)一些問題,如果需要使

用注釋,可以在XML中用來注釋,保證在生成的SQL中不會存在SQL注釋,

從而降低問題出現(xiàn)的可能性。這樣做還有一個好處,就是在IDE中可以很清楚

的區(qū)分注釋與SQL.

現(xiàn)在來談談注釋引發(fā)的問題,我做的一個項目中,分頁組件是基于Mybatis

的,它會在你寫的SQL腳本外面再套一層SELECTCOUNT(*)ROWNUM,

FROM(....)計算總記錄數(shù),同時有另一個嵌套SELECT*FROM(...)WHERE

ROWNUM>10ANDRONNUM<10*2這種方式生成分頁信息,如果你

的腳本中最后一行出現(xiàn)了注釋,則添加的部分會成為注釋的一部分,執(zhí)行就會

報錯。除此之外,某些情況下也可能導致部分條件被忽略,如下面的情況:

SELECT*FROMTEST

WHEREC0L1>1-這里是注釋ANDC0L2=#{a}

即使傳入的參數(shù)中存在對應的參數(shù),實際也不會產(chǎn)生效果,因為后面的內(nèi)容實

際上是被完全注釋了。這種錯誤,如果不經(jīng)過嚴格的測試,是很難發(fā)現(xiàn)的。-

般情況下,XML注釋完全可以替代SQL注釋,因此這種行為應該可以禁止掉。

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

Mybatis中盡量不要使用${},盡量這樣做很方便開發(fā),但是有一個問題,就

是大量使用會導致ORACLE的硬解析,拖慢數(shù)據(jù)庫性能,運行越久,數(shù)據(jù)庫

性能會越差。

關于${},另一個誤用的地方就是LIKE,我這邊還有個案例:比如一些樹型菜

單,節(jié)點會設計成’01':0101',用兩位節(jié)點來區(qū)分層級,這時候,如果需要查詢

01節(jié)點下所有的節(jié)點,最簡單的SQL便是:SELECT*FROMTREEWHEREID

LIKE6%',這種SQL其實無可厚非,因為它也能用到索引,所以不需要特別

的處理,直接使用就行了。但如果是文章標題,則需要額外注意了:SELECT*

FROMT_NEWS_TEXTWHERETITLELIKE'%OSC%',這是怎么也不會用到

索引的,上面說了,最好采用全文檢索。但如果離不開LIKE,就需要注意使用

的方式:IDLIKE#{ID}||'%'而不是IDLIKE'

有人覺得使用||會增加ORACLE處理的時間我覺得不要把ORACLE看得太傻,

雖然有時候確實非常傻,有空可以再總結(jié)ORACLE傻不垃圾的地方,但是稍

加測試便知:這種串聯(lián)方式,對于整個SQL的解析執(zhí)行,應該是微乎其微的。

當然還有一些特殊情況是沒有辦法處理的,比如說動態(tài)注入列名、表名等。對

于這些情況,則比較棘手,沒有找到比較方便的手段。由于這種情況出現(xiàn)的可

能性會比較少,所以使用ID有人覺得使用||會增加ORACLE處理的時間,我

覺得不要把ORACLE看得太傻,雖然有時候確實非常傻,有空可以再總結(jié)

ORACLE傻不垃圾的地方,但是稍加測試便知:這種串聯(lián)方式,對于整個SQL

的解析執(zhí)行,應該是微乎其微的。當然還有一些特殊情況是沒有辦法處理的,

比如說動態(tài)注入列名、表名等。對于這些情況,則比較棘手,沒有找到比較方

便的手段。由于這種情況出現(xiàn)的可能性會比較少,所以使用。倒也不至于有什

么太大的影響"當然你如果有代碼潔癖的話,可以使用ORACLE的動態(tài)執(zhí)行

SQL的機制Executeimmediate,這樣就可以完全避免${}出現(xiàn)的可能性了。

這樣會引入比較復雜的模型,這個時候,你就需要取舍了。

針對于以上動態(tài)SQL所導致的問題,最激進的方式是全部采用存儲過程,用

數(shù)據(jù)庫原生的方式來解決,方便開發(fā)調(diào)試,當然也會帶來問題:對開發(fā)人員會

有更高的要求、存儲過程的管理等等,我這邊項目沒有采用過這種方式,這里

不做更多的展開。

簡單使用Mybatise

Mybatis的功能相對而言還是比較弱的,缺少了好多必要的輔助庫,字符串處

理等等,擴展也比較困難,一般也就可能對返回值進行一些處理。因此最好僅

僅把它作為單純的SQL配置文件以及簡單的ORM框架。不要嘗試在Mybatis

中做過多的動態(tài)SQL,否則會導致后續(xù)的維護非常惡心。

幾點技巧總結(jié);

1、查詢很多字段時可以提出來再引入到sql語句

提?。?/p>

id,type,shopCouId,Path,fromDate^toDate^insDate>insUserld^

updDate,updUserld,delFlg

引入:

select

fromadinfo

whereid=#{id,jdbcType=INTEGER}

2、如果sql語句中需要使用<,符號時,需要使用<>"或者CDATA

內(nèi)部所有東西都會被解析器忽略

selecttype,shopCouId,Path

fromadinfo

WHEREdelFlg='0'

andfromDate<#{date}andtoDate>=#{date}

3、緩存使用

在增刪查改時,可以使用緩存屬性控制數(shù)據(jù)緩存

4、可以判斷傳進來的參數(shù),再進行操作

andlangCd=#{langCdjdbcType=VARCHAR}

5、可以在sql語句中直接進行加減乘除計算,模糊查詢時,需要注意使用方

SELECTsum(Cnt)+#{netCnt,jdbcType=INTEGER}

FROMcollectcntb

WHEREb.shopld=#{shopld>jdbcType=INTEGER)

ANDb.delflg='0'

newCnt=newCnt+1,

netCnt=netCnt+1,

sumCnt=sumCnt+1,

ANDo.oTimeLIKEC0NCAT('%',#{sdate),'%')

MyBatis把int類型的0處理成空串〃和mysql處理空串〃為0的問題

當數(shù)據(jù)庫字段類型是整數(shù),如果參數(shù)變量為空字符串或者NULL,Mybatis會

自動將參數(shù)賦值0,所以如果要判斷整數(shù)參數(shù)的多種狀態(tài)在傳遞數(shù)值到

Mapper之前就要判斷是否為空字符串和NULL并將相應的狀態(tài)數(shù)值賦值給該

參數(shù),否則參數(shù)值等于空字符串、NULL和0得到的結(jié)果是一樣的。

一般情況下,涉及到int類型的操作的時候,在Service中會統(tǒng)一把數(shù)字類型

先變成字符串類型,然后再傳遞到Mapper中操作。

案例六:

使用mybatis進行批量insert的時候會自動封裝成一個m叩key是list要

存的數(shù)據(jù)變成了數(shù)組需要注意在xml里面如果使用自己定義的collection要

在傳參時定義一個mapkey是自己定義的變量名哦。

在使用resultMap的時候,要把ID寫在第一行,否則的話,就會報錯。

優(yōu)缺點

總結(jié)下mybatis的優(yōu)缺點,以便大家對于mybatis的了解能更全面些。但我

所說的優(yōu)缺點,僅是我個人總結(jié)并結(jié)合使用體驗后得出的結(jié)果,并不能代表大

眾想法,因此才以“淺談"作為文章標題。如果大家的見解與我不同,歡迎積極

提出來一塊討論,我也借以彌補自己認識的不足和短見。

優(yōu)點:

1.易于上手和掌握。

2.sql寫在xml里,便于統(tǒng)一管理和優(yōu)化。

3.解除sql與程序代碼的耦合。

4.提供映射標簽,支持對象與數(shù)據(jù)庫的orm字段關系映射

5.提供對象關系映射標簽,支持對象關系組建維護

6.提供xml標簽,支持編寫動態(tài)sql。

缺點:

1.sql工作量很大,尤其是字段多、關聯(lián)表多時,更是如此。

2.sql依賴于數(shù)據(jù)庫,導致數(shù)據(jù)庫移植性差.

3.由于xml里標簽id必須唯一,導致DAO中方法不

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論