MyBatis學習總結(14)——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:
12345 | <select id="selectStudent">selects.code as sNo,s.name as sName,c.name as cNamefrom xStudents,xClasscwheres.cID=c.ID</select> |
如下宣告我們的dao方法:
1 2 3 |
publicList< |
如果要將該查詢結果轉為JSON字串返回,那麼我們就可以直接將List<Map<String, Object>轉為JSON,邏輯層不需要任何程式碼。
如果返回的結果集需要按select中的欄位順序返回,那麼將resultType=”java.util.HashMap” 換為resultType=”java.util.LinkedHashMap”
5、使用Map封裝查詢結果時注意資料的型別對映
對於如下的Mapper
1234 | <select id="selectStudent">selects.code as sNo,concat(s.firstName,s.lastName)as sNamefrom xStudents</select> |
Mybatis會傻傻的將sName的資料型別對映為byte[], 因為我們沒有提供entity,mybatis也不知道我們想要什麼型別,而sName是計算出來的值,mybatis也沒有辦法從資料庫中獲取欄位的值,所以它就將其封裝為byte[],解決辦法很簡單,加一個cast 函式
1 2 3 4 | <selectid="selectStudent"> selects.codeassNo,cast(concat(s.firstName,s.lastName)ASCHAR)assName fromxStudents </select> |
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。
1234567 | <configuration><settings>...<setting name="logImpl"value="LOG4J"/>...</settings></configuration> |
7、警惕Mybatis的Foreach的的副作用
對於如下SQL:
假設有如下的mapper:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <selectid=”testForeach”parameterType=”map”resultType=”Student”> Select*fromstudent <where> <iftest=”ID!=nullandID!=‘’”> ID=#{ID} </if> <iftest=”IDArr!=nullandIDArr.size()>0”> AndIDIN <foreachcollection="IDArr"open="(" separator=","close=")"item="ID"> ${ID} </foreach> </if> </where> </select> |
當我們傳入的IDArr時,最後產生的SQL為:
Select * from student where ID = ‘998’ AND ID IN ( ‘123’, ’234’,…..,’998’)
解決辦法:
解決辦法有
1) 將紅色的ID 換成別的名稱,比如“item”。
2) 這兩個if 是對同一個欄位判斷,改為choose… when 結構