51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Mybatis动态Sql详解

# (一)概述 {#一-概述}

mybatis官方中文网站对动态Sql的教程:https://mybatis.org/mybatis-3/zh/dynamic-sql.html

动态sql简单来讲就是我们能通过条件的设置生成不同的sql,在Mybatis中主要学习四种表达式即可:

  • if
  • choose (when, otherwise)
  • trim (where, set)
  • foreach

# (二)If {#二-if}

动态sql中最常见的场景是根据条件查询,比如现在我要实现一个查询语句,当不传任何参数时查询所有用户,当传了id或者name时根据条件进行查询,我就可以这样写:

<select id="SelectUserByMap" parameterType="map" resultType="map">
    select * from user where 1=1
    <if test="id != null">
        and id=#{id}
    </if>
    <if test="name != null">
        and name=#{name}
    </if>
</select>

通过下面的方式进行查询

Map<String,String> map=new HashMap<String, String>();
map.put("id","1");
map.put("name","javayz");
List<User> users = mapper.SelectUserByMap(map);

当map中什么都不传时,sql语句变为:

select * from user where 1=1

当传了id或name时,分别执行对应的语句。

你可能会奇怪我为什么要写一个1=1,这里后面会讲到。

# (三)choose、when、otherwise {#三-choose、when、otherwise}

choose的使用很像Java中的switch语法,当满足第一个when条件时,就不去看后续的条件,如果条件都不满足,则执行otherwise:

<select id="SelectUserByChoose" parameterType="map" resultType="com.javayz.pojo.User">
    select * from user where 1=1
    <choose>
        <when test="id != null">
            and id=#{id}
        </when>
        <when test="name != null">
            and name=#{name}
        </when>
        <otherwise>
            and 1=1
        </otherwise>
    </choose>
</select>

# (四)trim、where、set {#四-trim、where、set}

还记得我前面的语法中都写了where 1=1吗,至于为什么这样写,目的在于让语法能顺利执行,以if语句为例:如果不写1=1,语法就会变成下面这样

<select id="SelectUserByMap" parameterType="map" resultType="map">
    select * from user where
    <if test="id != null">
        id=#{id}
    </if>
    <if test="name != null">
        and name=#{name}
    </if>
</select>

这个时候如果满足了第一个if条件,那不会有问题,但是如果只满足第二个条件,语句就会变成:

select * from user where and name=?

语法直接报错。

Mybatis提供了一种标签来代替1=1的写法,where标签只会在子元素返回任何内容的情况下才插入 "WHERE" 子句。而且,若子句的开头为 "AND" 或 "OR",where 元素也会将它们去除。

因此上面的内容我可以改成:

<select id="SelectUserByMap" parameterType="map" resultType="map">
    select * from user
    <where>
        <if test="id != null">
            and id=#{id}
        </if>
        <if test="name != null">
            and name=#{name}
        </if>
    </where>
</select>

Set的实现和where类似,我们在更新时会用到set

<update id="UpdateUser" parameterType="map">
    update user
    <set>
        <if test="name != null">name =#{name},</if>
    </set>
    where id = #{id}
</update>

使用where时会用自动去替换掉and或者or,而使用set时会动态地在行首插入 SET 关键字,并会删掉额外的逗号。

使用trim可以用于去除拼接sql时的and、or关键字或者逗号等等。

之前我们使用where标签去除了最开始的and关键字,用trim也同样可以实现:

<select id="SelectUserByMap" parameterType="map" resultType="map">
    select * from user
    <trim prefix="where" prefixOverrides="and">
        <if test="id != null">
            and id=#{id}
        </if>
        <if test="name != null">
            and name=#{name}
        </if>
    </trim>
</select>

去除set末尾的逗号也可以使用trim

<trim prefix="SET" suffixOverrides=",">
  ...
</trim>

# (五)foreach {#五-foreach}

foreach在需要对集合进行遍历的场景中使用很广泛,尤其是在in语句中,下面我们来实现下面这条sql语句:

select * from user where id in (1,2,3,4)

    <select id="selectUserByForeach" parameterType="map" resultType="User">
        select * from user where id in
            <foreach collection="ids" item="id" index="index" open="(" separator="," close=")">
                #{id}
            </foreach>
    </select>

# (六)总结 {#六-总结}

至此,我们就把mybatis的动态sql学习完毕了,总体来讲动态Sql的使用并不算复杂,关键还是多练,孰能生巧。

赞(4)
未经允许不得转载:工具盒子 » Mybatis动态Sql详解