MyBatis中使用SQL动态绑定

2018-11-23  本文已影响0人  小安的大情调

如未作特殊说明,本文均为原创,转载请注明出处。

[TOC]

前言
同在在编写业务代码时,会经常遇到多条件查询语句。在普通SQL中使用多条件查询有一个投机取巧的方法就是在条件语句前面加上where 1 = 1恒成立的条件,这样就不用考虑第一个条件是否成立,where or and的使用顺序。

​ 但是使用where 1 = 1这种恒成立的语句,会主动放弃MySQL索引查询,如果数据库非常庞大,那会是一场灾难。

Mybatis中的动态绑定

准备:


标签表.png

SQL语句的实现条件选择。

if/choose/where/set

  1. IF:用if实现条件的选择,用于定义where的条件。
  2. choose:相当于java中的switch语句,通常whenotherwise一起使用。
  3. where:简化SQL语句中的where条件。
  4. set:解决SQL中更新语句。

下面简单的说明下这几种关键字的用法。

根据条件更新

    <update id="updateByPrimaryKeySelective" parameterType="com.tensquare.model.Label">
        update tb_label
        <set>
            <if test="labelname != null">
                labelname = #{labelname,jdbcType=VARCHAR},
            </if>
            <if test="state != null">
                state = #{state,jdbcType=VARCHAR},
            </if>
            <if test="count != null">
                count = #{count,jdbcType=BIGINT},
            </if>
            <if test="recommend != null">
                recommend = #{recommend,jdbcType=VARCHAR},
            </if>
            <if test="fans != null">
                fans = #{fans,jdbcType=BIGINT},
            </if>
        </set>
        where id = #{id,jdbcType=VARCHAR}
    </update>

choose:

    <select id="ChooseTest" resultMap="BaseResultMap" parameterType="com.tensquare.model.Label">
        SELECT * FROM tb_label
        WHERE 1=1
        <choose>
            <when test="id != null">
                AND id = #{id}
            </when>
            <when test="labelname != null">
                and labelname = #{labelname}
            </when>
            <otherwise>
                and count = #{count}
            </otherwise>
        </choose>
    </select>

这里使用了where 1 = 1来避免where 不知道哪一个判断正确的情况下。chooseJAVA中的swith类似,当遇到一个判断成立后,不会执行下面的。所以一般在使用动态sql查询时都使用<where></where>来自动提供在一个成立的条件前面不会添加and

SQL多条件查询中的like使用和## 、#`的区别

​ 在mybatis中使用模糊查询时,可以使用以下三种方式:

  1. 直接拼接。(占位符/字符拼接)

    select * from tb_label where labelname like "%"#{labelname}"%"
    
    或者
    
    select * from tb_label where labelname like '%${labelname}%'
    
  2. 使用concat(str1,str2)函数将两个两个参数连接起来

    select * from tb_label where labelname like concat("%",concat(#{labelname},"%"))
    
  3. 将参数使用bind标签绑定在一起(这里书写一个完整的多条件动态查询,在mybatis中)

     <select id="findBySearch" resultMap="BaseResultMap" parameterType="com.tensquare.model.Label">
            SELECT
            <include refid="Base_Column_List"/>
            FROM tb_label
            <where>
                <if test="id != null">
                    and id = #{id,jdbcType=VARCHAR}
                </if>
                <if test="labelname != null">
                      <bind name="newlabelname" value="'%'+labelname+'%'"/>
                      and labelname like #{newlabelname}
                </if>
                <if test="state != null">
                    and state = #{state}
                </if>
                <if test="count != null">
                    and count = #{count}
                </if>
                <if test="recommend != null">
                    and recommend = #{recommend}
                </if>
            </where>
        </select>
    
  4. #$的区别

在上面的第一种直接拼接的sql语句中可以看出,书写的方式不同,#有一种调用方法的感觉而$更像一种字符的拼接。

​ 这里可以指出#{}是一个占位符。而$则属于字符拼接。在安全方面来说,$相对来说比较容易被乘虚而入(SQL注入)。利于在判断语句中黑客添加依据判断作为拼接(labelname or 1=1)这样一来判断一定成立,数据就容易被窃取。

​ 在编译时,mybatis在控制台打印的sql语句不一样。

#

# 控制台打印sql.png
$: $ sql拼接 控制台sql语句.png
  1. 在mybatis sql拼接时出现下列错误:


    sql语句中?号与参数个数不符.png

    sql语句中出现的占位符(?)的个数与参数不符合。

总结

​ 加油!!!

上一篇下一篇

猜你喜欢

热点阅读