mybatis if各種用法


用mybatis執行數據庫操作僅僅能看到執行結果,如果想看到執行的sql語句怎么辦。

查閱mybatis官方文檔找到了解決方法。

配置什么的很簡單,用的log4j打印,當然參照官方文檔還有好幾種方法,具體自弄。

這里僅作記錄只用。配置很簡單,將log4j架包加入到classpath里。

maven配置。

        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

 

非maven項目只需要將jar添加到項目中即可。

log4j.properties添加到source根目錄。

復制代碼
# 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=DEBUG

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。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM