點滴記載,點滴進步,願本身更上一層樓。html
用mybatis執行數據庫操做僅僅能看到執行結果,若是想看到執行的sql語句怎麼辦。java
查閱mybatis官方文檔找到了解決方法。面試
配置什麼的很簡單,用的log4j打印,固然參照官方文檔還有好幾種方法,具體自弄。sql
這裏僅做記錄只用。配置很簡單,將log4j架包加入到classpath裏。數據庫
maven配置。apache
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
非maven項目只須要將jar添加到項目中便可。mybatis
log4j.properties添加到source根目錄。app
# Global logging configuration log4j.rootLogger=ERROR, stdout # MyBatis logging configuration... #log4j.logger.com.soft.test.dao=DEBUG log4j.logger.dynamic=DEBUG #log4j.logger.org.mybatis.example.BlogMapper=TRACE # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
其中關鍵的地方是
log4j.logger.dynamic=DEBUGmaven
log4j.logger是固定的,dynamic爲你的mapper.xml的namespace測試
若是個人xml中的namespace爲dynamic
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <!-- namespace命名空間,跟java的package相似,避免sql id重複, 有了這個命名空間,別的xml中的sql的id能夠跟這個重複,而且 namespace不能省略,不能爲空,不用接口開發,此處能夠隨意寫--> <mapper namespace="dynamic"> <resultMap id="userMap" type="com.soft.test.model.User"> <id column="id" property="id"/> <result column="username" property="username"/> <result column="password" property="password"/> <result column="create_date" property="createDate"/> </resultMap> <!--if 標籤使用相似html的C標籤的if --> <select id="selectUseIf" parameterType="com.soft.test.model.User" resultMap="userMap"> select * from t_user where <if test="id != null and id != ''"> id=#{id} </if> <if test="username != null and username != ''"> and username like concat('%',#{username},'%') </if> <if test="password != null and password != ''"> and password=#{password} </if> </select> </mapper>
配置完成。如今運行測試便可看到運行的sql語句
------------------------------------------------------------------------------------------------------------------------------
DEBUG [main] - ==> Preparing: select * from t_user where id=? and username like concat('%',?,'%')
DEBUG [main] - ==> Parameters: 28(Integer), xiao(String)
DEBUG [main] - <== Total: 1
-------------------------------------------------------------------------------------------------------------------------------
mybatis的if判斷語句其實跟el表達式的if條件判斷有些相似。
例如: <if test="id != null"> </if>
1 若是參數爲數字類型的時候沒有特俗需求的狀況只須要判斷是否爲null便可。
例如:<if test="id != null"></if>
若是有特俗需求,例如判斷是否大於某個數的時候才行。只須要加上對應的條件判斷便可
例如:<if test='id != null and id > 28'></if>
mybatis對於這種大於小於等等還有另外一種形式。
例如:<if test='id != null and id gt 28'></if>
對應關係:
---------------------------------------
gt 對應 >
gte 對應 >=
lt 對應 <(會報錯 相關聯的 "test" 屬性值不能包含 '<' 字符)
lte 對應 <=(會報錯 相關聯的 "test" 屬性值不能包含 '<' 字符)
---------------------------------------
2 若是爲字符串類型
2.1 若是不須要過濾空串的狀況 僅僅判斷null便可
例如:<if test="username != null"></if>
2.2 若是須要過濾空串,添加空串判斷便可 不支持 && 因此這裏用 and or || 來作邏輯與或的判斷
例如:<if test="username != null and '' != username"></if> 或者 <if test="username != null and '' neq username"></if>
2.3 若是判斷字符串是否已某個特俗字符開頭,結尾等。直接調用String的對應方法便可
例如:<if test="username != null and username.indexOf('ji') == 0"> </if> <!-- 是否以什麼開頭 -->
<if test="username != null and username.indexOf('ji') >= 0"> </if> <!-- 是否包含某字符 -->
<if test="username != null and username.lastIndexOf('ji') > 0"></if> <!-- 是否以什麼結尾 -->
2.4 是不是某個特定字符串,某些業務有此須要。
例如:<if test="username != null and 'hello' == username"></if> 或者<if test="username != null and 'hello' eq username"></if>
注意:
<if test="username != null and 'hello' == username"></if>這種形式的寫法在參數類型是字符串的時候是沒有問題的,
可是參數類型爲非字符串類型的時候就須要寫成 <if test="username != null and 'hello'.toString() == username.toString()"></if>
僅僅寫成<if test="username != null and 'hello'.toString() == username"></if>也會有很大可能會掛。
也許你會說非字符串的爲何要寫成這樣。這就要看特俗須要了。
例如:某一個sql片斷是公用的,
<if test="username != null"></if>
<if test="password != null"></if>
該片斷更新條件也用,可是當你須要將某一個字段更新成null的時候怎麼辦。
這個時候就能夠經過傳入一個特定的字符串來弄。當傳入的字符串爲特定字符串的時候就更新該字符串爲null。
<if test="username != null and 'hello'.toString() == username.toString()">xxx=null</if>
固然這樣子貌似date型會掛。
經過 2.2 也能夠看出mybatis對於字符串的相等不相等的判斷也是有對應的特俗操做符的。
-------------------------------------------------------
eq 對應 ==
neq 對應 !=
------------------------------------------------------
固然還能夠看出來if的條件判斷test是支持對象自身方法調用的,即便是本身寫的方法,能夠本身嘗試。固然下面會有例子。
例如:裏面能夠用‘xxxx’.equals(xxxx) 字符串的比較兩個字符串方法
xxxx.indexOf('ss') 判斷字符串裏面是否包含某個字符等等
3 判斷list是否爲空
上面說過,if條件判斷能夠直接調用對象自身的方法進行邏輯判斷,因此list判空。能夠調用.size()>0或者.isEmpty()
例如:<if test="userList != null and userList.isEmpty()"></if> , <if test="userList != null and userList.size()>0"></if>
4 map參數同同理 取值的話 map.key(map中的key名字)便可
----------------------------------------------------------------------------------------------分割線01-----------------------------------------------------------------------------------------------------------
這裏是上面的各類理論的實踐。這裏能夠不看,本身去實踐最好。
1 數字類型。
僅做null判斷。
<!--if 標籤使用相似html的C標籤的if --> <select id="selectUseIf" parameterType="com.soft.test.model.DynamicTestModel" resultMap="userMap"> select * from t_user where 1=1 <if test='id != null'> and id=#{id} </if> </select>
當id不爲null的時候 打印的log
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and id=?
DEBUG [main] - ==> Parameters: 28(Integer)
DEBUG [main] - <== Total: 1
當id爲null的時候 打印的log
DEBUG [main] - ==> Preparing: select * from t_user where 1=1
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 1
兩項對比,能夠看出id=?這個條件隨着傳入參數id的變化而變化。
當有特俗需求的時候,當前數據庫中的表id爲28 僅僅有這麼一條數據,作一下輕微的改動
<if test='id != null and id > 27 '>
當傳入id=28的時候
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and id=?
DEBUG [main] - ==> Parameters: 28(Integer)
DEBUG [main] - <== Total: 1
當傳入id小於28的時候
DEBUG [main] - ==> Preparing: select * from t_user where 1=1
DEBUG [main] - ==> Parameters:
DEBUG [main] - <== Total: 1
接下來測試下面這幾種對應關係。
---------------------------------------
gt 對應 >
gte 對應 >=
lt 對應 <(會報錯 相關聯的 "test" 屬性值不能包含 '<' 字符)
lte 對應 <=(會報錯 相關聯的 "test" 屬性值不能包含 '<' 字符)
---------------------------------------
gt
<if test='id != null and id gt 27 '>
參數 id=25
DEBUG [main] - ==> Preparing: select * from t_user where 1=1
DEBUG [main] - ==> Parameters:
參數 id=28
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and id=?
DEBUG [main] - ==> Parameters: 28(Integer)
>=
<if test='id != null and id >= 28 '>
參數 id=28
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and id=?
DEBUG [main] - ==> Parameters: 28(Integer)
參數 id=27
DEBUG [main] - ==> Preparing: select * from t_user where 1=1
DEBUG [main] - ==> Parameters:
gte
<if test='id != null and id gte 28 '>
參數 id=28
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and id=?
DEBUG [main] - ==> Parameters: 28(Integer)
參數 id=27
DEBUG [main] - ==> Preparing: select * from t_user where 1=1
DEBUG [main] - ==> Parameters:
使用 < <= 直接報錯 "test" 屬性值不能包含 '<' 字符 看來只能用 lt lte了
lt
<if test='id != null and id lt 28 '>
參數 id=28
DEBUG [main] - ==> Preparing: select * from t_user where 1=1
DEBUG [main] - ==> Parameters:
參數 id=27
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and id=?
DEBUG [main] - ==> Parameters: 27(Integer)
lte
<if test='id != null and id lte 28 '>
參數 id=28
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and id=?
DEBUG [main] - ==> Parameters: 28(Integer)
參數 id=29
DEBUG [main] - ==> Preparing: select * from t_user where 1=1
DEBUG [main] - ==> Parameters:
----------------------------------------------------------------------------------------------分割線02-----------------------------------------------------------------------------------------------------------
2.1 跟1的第一條同樣不作重複測試
2.2 過濾空串
<select id="selectUseIf" parameterType="com.soft.test.model.DynamicTestModel" resultMap="userMap"> select * from t_user where 1=1 <if test="username != null and '' != username "> and username=#{username} </if> </select>
!=
username=「xiao」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and username=?
DEBUG [main] - ==> Parameters: xiao(String)
username=「」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1
DEBUG [main] - ==> Parameters:
neq
<if test="username != null and '' neq username ">
username=「xiao」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and username=?
DEBUG [main] - ==> Parameters: xiao(String)
username=「」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1
DEBUG [main] - ==> Parameters:
各個邏輯與或的判斷
and上面已經弄過了,這裏弄or || 兩種條件
<if test="'xiaohong' eq username or 'xiao' eq username ">
or
username=「xiao」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and username=?
DEBUG [main] - ==> Parameters: xiao(String)
username=「xiaohong」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and username=?
DEBUG [main] - ==> Parameters: xiaohong(String)
username=「xiaofang」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1
DEBUG [main] - ==> Parameters:
||
username=「xiao」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and username=?
DEBUG [main] - ==> Parameters: xiao(String)
username=「xiaohong」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and username=?
DEBUG [main] - ==> Parameters: xiaohong(String)
username=「xiaofang」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1
DEBUG [main] - ==> Parameters:
2.3 indexOf() lastIndexOf() 判斷是否包含某個特定字符
<if test="username != null and username.indexOf('xiao')==0">
username=「xiao」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and username=?
DEBUG [main] - ==> Parameters: xiao(String)
username=「xiaofang」
DEBUG [main] - ==> Preparing: select * from t_user where 1=1 and username=?
DEBUG [main] - ==> Parameters: xiaofang(String)
其餘兩個沒什麼大不一樣的。自行測試。
2.4 判斷是不是某個字符
<if test="'xiaohong' eq username">
username=「xiaohong」
==> Preparing: select * from t_user where 1=1 and username=?
==> Parameters: xiaohong(String)
username=「xiaofang」
==> Preparing: select * from t_user where 1=1
==> Parameters:
3 4 的本質就是再說mybatis的if條件判斷語句能夠直接執行對象的方法。下面本身寫一個方法,在if裏面試試。
本身定義一個類,裏面一個方法用於條件判斷用。
public class DynamicSql1Model { public boolean getMySelfMethod(){ return true; } }
該類做爲一個屬性放入到model中 僅僅貼出部分代碼
public class DynamicSqlModel { private int id; private String username; private String password; private Date createDate; private List<String> list; private Map<String,Object> mapParam; private DynamicSql1Model dynamicSql1Model;
xml中引用該model的方法
<if test="dynamicSql1Model.getMySelfMethod()">
開始測試
DynamicSqlModel user = new DynamicSqlModel(); user.setUsername("xiaofang"); user.setPassword("123456"); user.setCreateDate(new Date()); DynamicSql1Model dynamicSqlModel = new DynamicSql1Model(); user.setDynamicSql1Model(dynamicSqlModel); dao.selectUseIf(user);
如今返回結果
如今方法的返回值爲true
==> Preparing: select * from t_user where 1=1 and username=?
==> Parameters: xiaofang(String)
方法返回值修改成false
==> Preparing: select * from t_user where 1=1
==> Parameters:
能夠看出徹底能夠使用自定義的方法進行if條件控制。經過該特性能夠幹一些特俗業務的事情。本身體會。
本篇說的主要是if條件判斷動態控制sql。能夠看出有弊端。由於if條件不知足的時候sql會變成
select * from t_user where 因此我在條件後面加了個 1=1 可是這是不符合邏輯的。下節介紹where以及其餘標籤用於動態sql。