Mybatis学习四(动态SQL)

    Mybatis的强大特性之一便是它的动态SQL,它帮助我们很好的完成SQL语句的拼接。我们来学习一下MyBatis的动态SQL在XML中的几种标签。

一、if用法

        if标签通常用在WHERE条件语句中,通过判断参数值来决定是否使用某个查询条件,它也经常用于UPDATE语句中判断是否更新某一个字段,也可以在INSERT语句中用来判断是否插入某个字段的值。

    1、在WHERE条件中使用if

            需求:输入用户名时,根据用户名模糊查询;输入邮箱时,根据邮箱精确匹配;都输入时,两个条件都用。

       Mapper接口添加方法如下:

List<SysUser> selectByNameAndEmail(@Param("userName")String userName,@Param("userEmail")String userEmail);

        Mapper文件添加如下:

    <!--if标签的使用,if标签有一个必填的test属性,是一个符合OGNL的表达式,结果可以是true或false,所有的非0都为true,0为false。-->
    <select id="selectByNameAndEmail" resultType="SysUser">
        SELECT id,user_name,user_password,user_email,user_info,head_img,create_time
        FROM sys_user WHERE	1=1
        <if test="userName != null and userName != ''">
	        AND user_name LIKE CONCAT( '%', #{userName}, '%' )
        </if>
        <if test="userEmail != null and userEmail != ''">
            AND user_email = #{userEmail}
        </if>
    </select>

        测试可用,1=1 是为了避免生成不正确的SQL(两个if都不符合时,多出来一个WHERE),可以在后续使用where标签。

    2、在UPDATE中使用if

       需求:只更新发生变化的字段

    Mapper接口添加如下:

    /**
     * 一般情况下MyBatis中选择性更新方法名会以Selective作为后缀
     */
    int updateByIdSelective(SysUser sysUser);

    Mapper文件添加如下:

    <update id="updateByIdSelective">
        UPDATE sys_user SET
        <if test="userName != null and userName != ''">
            user_name = #{userName},
        </if>
        <if test="userPassword != null and userPassword != ''">
            user_password = #{userPassword},
        </if>
        <if test="userEmail != null and userEmail != ''">
            user_email = #{userEmail},
        </if>
        <if test="userInfo != null and userInfo != ''">
            user_info = #{userInfo},
        </if>
        <if test="headImg != null">
            head_img = #{headImg},
        </if>
        <if test="createTime != null">
            create_time = #{createTime},
        </if>
        id = #{id}
        WHERE id = #{id}
    </update>

    测试可用,set中 id=#{id}的作用是防止SQL拼接错误,后续可以使用set标签。

    3、在INSERT动态插入列中使用if

            需求:插入参数不为空的值

    Mapper接口添加如下:

int insertUser(SysUser sysUser);

    Mapper文件添加如下:

    <!--在列的部分增加if时,在VALUES中也要添加相同的if-->
    <insert id="insertUser">
        INSERT INTO sys_user(user_name,
        <if test="userPassword != null and   userPassword != ''">
            user_password,
        </if>
        user_email,user_info, head_img, create_time
        ) VALUES (#{userName},
        <if test="userPassword != null and   userPassword != ''">
            #{userPassword},
        </if>
        #{userEmail},#{userInfo}, #{headImg}, #{createTime})
    </insert>

        测试可用。

二、choose用法

    if标签提供了基本的条件判断,但是它没办法实现if...else、if...else...的逻辑,想实现这样的逻辑就需要用到choose when otherwise 标签。choose中包含when和otherwise两个标签,一个choose中至少有一个when,0或1个otherwise。

    需求:当有id的时候用id查询,没有id时,用用户名查询,都没有,使SQL查询无果。

    Mapper接口添加如下:

    SysUser selectByIdOrUserName(@Param("id")Long id,@Param("userName") String userName);

    Mapper文件添加如下:

    <select id="selectByIdOrUserName" resultType="SysUser">
        SELECT * FROM sys_user WHERE
        <choose>
            <when test="id != null and id != ''">
                id = #{id}
            </when>
            <when test="userName != null and userName != ''">
                user_name = #{userName}
            </when>
            <otherwise>
                1=2
            </otherwise>
        </choose>

    </select>

    测试可用

三、where用法

       where标签作用:如果该标签包含的元素有返回值,就插入一个where;如果where后面的字符串使以AND和OR开头的,就将它们剔除。

        需求:使用where标签修改一、1中的Mapper文件

    <select id="selectByNameAndEmail" resultType="SysUser">
        SELECT id,user_name,user_password,user_email,user_info,head_img,create_time
        FROM sys_user
        <where>
            <if test="userName != null and userName != ''">
                AND user_name LIKE CONCAT( '%', #{userName}, '%' )
            </if>
            <if test="userEmail != null and userEmail != ''">
                AND user_email = #{userEmail}
            </if>
        </where>
    </select>

四、set用法

    set标签作用:如果该标签包含的元素中有返回值,就插入一个set;如果set后面的字符串是以逗号结尾的,就将这个逗号删除。但是如果set中没有内容,照样会出现SQL错误,为避免错误的产生,类似id=#{id}这样必然存在的值仍然有保留的必要。

    需求:修改一、2中的Mapper文件 

    <update id="updateByIdSelective">
        UPDATE sys_user 
        <set>
            <if test="userName != null and userName != ''">
                user_name = #{userName},
            </if>
            <if test="userPassword != null and userPassword != ''">
                user_password = #{userPassword},
            </if>
            <if test="userEmail != null and userEmail != ''">
                user_email = #{userEmail},
            </if>
            <if test="userInfo != null and userInfo != ''">
                user_info = #{userInfo},
            </if>
            <if test="headImg != null">
                head_img = #{headImg},
            </if>
            <if test="createTime != null">
                create_time = #{createTime},
            </if>
            id = #{id}
        </set>
        WHERE id = #{id}
    </update>

 五、trim用法

        where和set标签的功能都可以用trim实现,在底层就是通过TrimeSqlNode实现的。

        trim属性如下:

            prefix : 当trim元素内包含内容时,会给内容增加prefix指定的前缀。

            prefixOverrides : 当trim元素内包含内容时,会把内同中匹配的前缀字符串去掉。

            suffix :当trim元素内包含内容时,会给内容增加指定的后缀。

            suffixOverrides : 当trim元素内包含内容时,会把内同中匹配的后缀字符串去掉。

        where标签对应的trim实现如下:

      <trim prefix="WHERE" prefixOverrides="AND | OR " >
            ...
        </trim>

        set标签对应的trim实现如下:

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

六、foreach用法

        属性:

            collection : 必填,值为要迭代循环的属性名。

            item : 变量名,值为从迭代对象中取出的每一个值。

            index : 索引属性名,在集合数组情况下值为当前索引值,在迭代循环的对象时map时,为map的key。

            open : 循环开头的字符串。

            close :循环结束的字符串。

            separator : 每次循环的分隔符。

    1、foreach实现in集合

        需求:根据id集合查询用户

Mapper接口添加如下:

List<SysUser> selectByIdList(@Param("ids") List<Long> ids);

Mapper文件添加如下:

    <select id="selectByIdList" resultType="SysUser">
        SELECT * FROM  sys_user WHERE id IN
        <foreach collection="ids" open="(" close=")" item="id" separator="," index="i">
            #{id}
        </foreach>
    </select>

使用@Param指定参数的名字,没有那么多事,什么List集合要用list,数组要用array。

    2、foreach实现批量插入

    需求:批量插入用户信息

Mapper接口添加如下:

int insertList(@Param("userList")List<SysUser> userList);

Mapper文件添加如下:

    <insert id="insertList">
        INSERT INTO sys_user(user_name,user_password,user_email,user_info,head_img,create_time)
        VALUES
        <foreach collection="userList" item="user" separator=",">
            (#{user.userName},#{user.userPassword},#{user.userEmail},#{user.userInfo},#{user.headImg},#{user.createTime})
        </foreach>
    </insert>

    测试可用

    3、foreach实现动态UPDATE

        需求:使用map作为参数修改

Mapper接口:

int updateByMap(Map<String,Object> map);

Mapper文件:

    <!--MyBatis在内部上下文中使用了默认值_parameter作为参数key。-->
    <update id="updateByMap">
        UPDATE sys_user SET
        <foreach collection="_parameter" item="val" index="key" separator=",">
            ${key} = #{val}
        </foreach>
        WHERE id = #{id}
    </update>

 

源码:https://gitee.com/itcaofanqi/CaoFanqiStudyRepository/tree/master/stumybatis

 

转载于:https://my.oschina.net/caofanqi/blog/3011675

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值