Bootstrap

MyBatis中动态sql的if条件判断的各种使用方式

在最近的项目工作中,对于mybatis的sql动态判断需要学习。所以在这里记录一下学习的过程与心得。

目录

前言

一、if判断语句过滤不同参数的处理

1.数字类型

2.字符串类型

二、测试与结果

1.数字类型

2.字符串类型

总结



前言

mybatis的动态sql拼接让很多复杂业务的处理变得简单化,开发人员只需要在xml文件中直接编写sql语句即可。再使用框架提供的方法,即可动态生成sql语句所需要的条件。但是在工作过程中。mybatis的if条件判断用法也需要一些技巧。

一、if判断语句过滤不同参数的处理

1.数字类型

1 如果参数为数字类型的时,且没有特殊需求的情况只需要判断是否为null即可。

<if test="id != null"></if>

2 如果有特殊需求,例如判断是否大于某个数的时候才行。只需要加上对应的条件判断即可

<if test='id != null and id > 28'></if>

3 mybatis对于这种大于小于等等还有另一种形式。

<if test='id != null and id gt 28'></if>

对应关系:

数学符号与sql写法的对应关系
写法对应
gt>
gte>=
lt<(会报错  相关联的 "test" 属性值不能包含 '<' 字符)
 lte<=(会报错  相关联的 "test" 属性值不能包含 '<' 字符)

2.字符串类型

1 如果不需要过滤空串的情况 仅仅判断null即可

<if test="username != null"></if>

2 如果需要过滤空串,添加空串判断即可,写法不支持 &&,所以这里用 and和or来做逻辑与或的判断 

<if test="username != null and '' != username"></if> 或者 <if test="username != null and ''  neq username"></if>

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>

 <!-- 是否以什么结尾 -->

4 是否为特定字符串,某些业务需要判断

<if test="username != null and 'hello' == username"></if> 或者<if test="username != null and 'hello' eq username"></if>

5 这里有个需要注意的点:如果参数类型是字符串的话,这么写是没问题的。

<if test="username != null and 'hello' == username"></if>

但是参数类型为非字符串类型的时候就需要写成,否则可能会挂

<if test="username != null and 'hello'.toString() == username.toString()"></if>

6 if的条件判断test是支持对象自身方法调用的,即使是自己写的方法,可以自己尝试。当然下面会有例子。

例如:里面可以用‘xxxx’.equals(xxxx) 字符串的比较两个字符串方法,xxxx.indexOf('ss') 判断字符串里面是否包含某个字符等等  

7 判断list是否为空

上面说过,if条件判断可以直接调用对象自身的方法进行逻辑判断,所以list判空。可以调用.size()>0或者.isEmpty()

<if test="userList != null and userList.isEmpty()"></if> , <if test="userList != null and userList.size()>0"></if>

二、测试与结果

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的变化而变化。

接下来测试下面这几种对应关系。  

数学符号与sql写法的对应关系
写法对应
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: 

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: 

  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)

其他两个没什么大不同的。自行测试。

 判断是否是某个字符

<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: 

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。


参考

https://www.cnblogs.com/sumlen/p/11130554.html

;