Mybatis中<where>标签 后 1=1 的作用

情景分析
工作当中,动态sql经常会用到,当遇到多个查询条件时,我们可能会写出类似下面这样的sql

<select id="selectUserByUsernameAndSex" resultType="user" parameterType="com.ztt.User">
    select * 
    from user 
    where
        <if test="username != null">
           username=#{username}
        </if>
         
        <if test="username != null">
           and sex=#{sex}
        </if>
</select>

这样写会产生很大问题,

如果没有匹配的条件,最终这条 SQL 会变成这样:select * from user where

如果username为空,最终这条 SQL 会变成这样:select * from user where and sex=#{sex}

这两种情况都会产生错误的sql语句。
解决方案
针对这种情况,有人想出了一个办法,就是人工的加一个结果必定为true的条件,比如where 1=1。那么我们的sql就会变成下面这样:

<select id="selectUserByUsernameAndSex" resultType="user" parameterType="com.ztt.User">
    select * 
    from user 
    where
        1 = 1
        <if test="username != null">
           and username=#{username}
        </if>
         
        <if test="username != null">
           and sex=#{sex}
        </if>
</select>

这样,不管if里面的判断如何,都能保证最终的sql语句是正确的。

但是这样很可能会造成非常大的性能损失,因为添加了 “where 1=1 ”的过滤条件之后,数据库系统就无法使用索引等查询优化策略,数据库系统将会被迫对每行数据进行扫描(即全表扫描) 来比较此行是否满足过滤条件,当表中的数据量较大时查询速度会非常慢;此外,还会存在SQL 注入的风险。

(实际上where 1=1 也会走索引,不影响查问效率,咱们写的sql指令会被mysql 进行解析优化成本人的解决指令,在这个过程中 1 = 1 这类无意义的条件将会被优化。)

那么有什么更好的替换方案呢?答案是使用使用标签。

where标签只会在它包含的标签中有返回值的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where标签也会将它们去除。

使用where标签后,我们的sql就变成了下面这样:

<select id="selectUserByUsernameAndSex" resultType="user" parameterType="com.ztt.User">
    select * from user
    <where>
        <if test="username != null">
           username=#{username}
        </if>
         
        <if test="username != null">
           and sex=#{sex}
        </if>
    </where>
</select>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值