Mybatis使用常見技巧

Mybatis 使用技巧總結

 Sep 11, 2014 |  Nix.Huang |  Say Something

目錄:
1、區分 #{} 和 ${}的不同應用場景
2、spring環境用mybatis-spring 的接口而不是Mybatis的原生接口
3、返回Map<ID, Entity>而不是List便於查找
4、使用Map封裝查詢的結果
5、使用Map封裝查詢結果時注意數據的類型映射
6、正確的配置Mybatis 的Log
7、警惕Mybatis的foreach的的副作用
8、使用原生的SQL操作數據以提高效率
9、警惕MyBatis封裝數據時性能損耗

1、 區分 #{} 和 ${}的不同應用場景

1)#{} 會生成預編譯SQL,會正確的處理數據的類型,而${}僅僅是文本替換。
對於SQL: select * from student where xCode = 'S123456';
如果使用#{}
那麼生成的SQL爲:
select * from student where xCode = ? 傳的值爲'S123456';
如果使用${}
那麼生成的SQL爲:select * from student where xCode = S123456
如果xCode的數據類型爲varchar,那麼使用${}就會報錯。
2)${}一般用在order by, limit, group by等場所。
假設我們使用#{} 來指定order by字段,比如
select * from student order by #{xCode},
那麼產生的SQL爲
select * from student order by ?, 替換值後爲
select * from student order by 'xCode'
Mybatis對xCode加了引號導致排序失敗

2、Spring環境用Mybatis-Spring的接口而不是Mybatis的原生接口

在spring 環境使用mybatis-spring的好處有:
1)我們可以使用Sping的聲明式事務處理模型(@Transactional),而不用手動迴歸事務。
2)mybatis-spring會優雅的關閉SqlSession,而不用手動關閉
3)可以將數據庫連接池交給spring管理,當程序停止的時候,spring會合適的關閉連接

3、返回Map<ID, Entity>而不是List便於查找

有時太多的表連接(join)性能太差,我們會將該SQL拆爲多個SQL,然後在代碼中組裝起來。比如學生表和班級表,需要查詢的結果爲"學號,班級,姓名",我們可以先查詢“學號,班級ID,姓名”以及“班級ID,班級名次”,我們可以在查詢班級表的時候返回Map<班級ID, 班級>, 然後迭代學生表的結果集,用班級ID到Map<班級ID, 班級>中查找對應的班級信息,然後用班級名稱替換班級ID。
接口聲明爲SqlSession.selectMap(String statement, String mapKey)

4、使用Map封裝查詢的結果

有時我們厭倦了爲每個查詢寫一個Entity類,這時Map開始發揮它的功效。
對於要返回“學號,班級,姓名”結果的查詢,可以這樣寫Mapper:

如下聲明我們的dao方法:

如果要將該查詢結果轉爲JSON字符串返回,那麼我們就可以直接將List<Map<String, Object>轉爲JSON,邏輯層不需要任何代碼。
如果返回的結果集需要按select中的字段順序返回,那麼將resultType="java.util.HashMap" 換爲resultType="java.util.LinkedHashMap"

5、使用Map封裝查詢結果時注意數據的類型映射

對於如下的Mapper

Mybatis會傻傻的將sName的數據類型映射爲byte[], 因爲我們沒有提供entity,mybatis也不知道我們想要什麼類型,而sName是計算出來的值,mybatis也沒有辦法從數據庫中獲取字段的值,所以它就將其封裝爲byte[],解決辦法很簡單,加一個cast 函數

6、正確的配置Mybatis 的Log

1)一個應用一般會使用很多的jar,各個jar依賴的log 實現不一樣,Mybatis查找Log的順序爲(SLF4J,Apache Commons Logging,Log4j 2,Log4j,JDK logging),如果classpath中有slf4j記得添加相應的橋接jar,比如slf4j-log4j。許多web 服務器的classpath 會含有Apache Commons Logging,因此如果要使用Log4j,要麼使用SLF4J橋接Log4j,要麼在配置中強制指定使用Log4J。

7、警惕Mybatis的Foreach的的副作用

對於如下SQL:
假設有如下的mapper:

當我們傳入的IDArr時,最後產生的SQL爲:
Select * from student where ID = ‘998’ AND ID IN ( ‘123’, ’234’,…..,’998’)
解決辦法:
解決辦法有
1) 將紅色的ID 換成別的名稱,比如“item”。
2) 這兩個if 是對同一個字段判斷,改爲choose… when 結構

8、使用原生的SQL操作數據以提高效率

對於一次插入多條數據,將其組裝成 insert into xxx values (), () ()格式一次插入多行數據往往能極大的提高性能。

9、警惕MyBatis封裝數據時性能損耗

對於如下的mapper

在一個批處理程序中循環的調用了該方法250次,每次返回大概1w條記錄,發現這個程序運行的很慢,用jrofiler 查看各個方法耗費的時間,居然80%的時間花在了student的setter上了,在這個過程中大概產生了250w個對象,而mybatis是利用發射封裝Entity,代碼大致如下:

解決的辦法是讓返回的行數和返回的字段儘量的少。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章