Mybatis中实现动态SQL

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介: Mybatis中实现动态SQL

1 背景

不建议使用,但是有些需求又不得不用回来温习下。动态SQL语句,也就意味着SQL语句不在是一成不变的而是具有多样性.

2 if判断

if的用法还是跟平常差不多的(不过没有else if也没有else)

<update id="modify" parameterType="User">
        UPDATE `smbms_user`
        <trim prefix="set" suffixOverrides="," suffix="where id=#{id}">
            <if test="userCode!=null">`userCode` = #{userCode} , </if>
            <if test="userName!=null">`userName` = #{userName} , </if>
            <if test="userPassword!=null">`userPassword` = #{userPassword} , </if>
            <if test="gender!=null">`gender` = #{gender} , </if>
            <if test="birthday!=null">`birthday` = #{birthday} ,</if>
            <if test="phone!=null">`phone` = #{phone} , </if>
            <if test="address!=null">`address` = #{address} , </if>
            <if test="userRole!=null">`userRole` = #{userRole} , </if>
            <if test="createdBy!=null">`createdBy` = #{createdBy} , </if>
            <if test="creationDate!=null">`creationDate` = #{creationDate} , </if>
            <if test="modifyBy!=null">`modifyBy` = #{modifyBy}</if>
        </trim>
    </update> 

如上面的代码,如果是空的字段则不执行更新操作

2 choose(when,otherwise)选择分支进入

choose就相当于Java中的switch,when相当于case,otherwise相当于default

<select id="getBill" resultType="Bill">
        SELECT * FROM smbms_bill b JOIN smbms_provider p  ON b.providerId=p.id
        WHERE 1=1
        <choose>
            <!-- 条件为false则继续执行下面的when,反之亦然如此 -->
            <when test="id!=null">
                AND    b.providerId=#{id} 
            </when>
            <!-- 条件为true则不会执行otherwise,反之亦然如此 -->
            <when test="proName!=null">
                AND p.proName LIKE CONCAT('%',#{proName},'%')
            </when>
            <!-- 当都不满足时执行默认值 -->
            <otherwise>
                AND p.proContact LIKE CONCAT('%张%')
            </otherwise>
        </choose>
    </select>

3 where

此标签可以忽略条件中多余的and和or如下

SELECT * FROM smbms_bill b JOIN smbms_provider p  ON b.providerId=p.id
        <where>
            <if test="id!=null">
                 AND b.providerId=#{id}
            </if>
            <if test="proName!=null">
                 AND p.proName LIKE CONCAT('%',#{proName},'%')
            </if>
        </where>

假设id为1 proName为北京 两个if都满足条件时就会拼凑成这样

SELECT * FROM smbms_bill b JOIN smbms_provider p  ON b.providerId=p.id WHERE b.providerId=1 AND p.proName LIKE CONCAT('%北京%')

其实解决这种情况不用where也是可以的,只需在前面加上一个为真的条件即可

SELECT * FROM smbms_bill b JOIN smbms_provider p  ON b.providerId=p.id
        where 1=1
        <if test="id!=null">
             AND b.providerId=#{id}
        </if>
        <if test="proName!=null">
             AND p.proName LIKE CONCAT('%',#{proName},'%')
        </if>

效果也是一样的

4 set

此标签可以忽略多余的逗号

UPDATE `smbms_user` 
        <set>
            <if test="userPassword!=null">
                `userPassword` = #{userPassword},
            </if>
        </set>
           WHERE `id` = #{id} ;

5 trim

此标签属性如下

  1. prefix:通过自动识别是否有返回值,在trim包含的内容上加上前缀
  2. suffix:在trim包含的内容上加上后缀
  1. prefixoverrides:对trim包含内容的首部进行指定内容的忽略
  2. suffixoverrides;对于trim包含内容的尾部进行指定内容的忽略

栗子1

<!-- 添加内容前面加上 where 并且忽略 and或者or -->
        <trim prefix="where" prefixOverrides="and|or">
            <if test="userRole!=null">
                and userRole=#{userRole}
            </if> 
            <if test="userName!=null and userName!=''">
                and u.userName like CONCAT('%',#{userName},'%')
            </if>
            order by creationDate DESC limit #(from),#(pageSize)
        </trim>

栗子2

UPDATE `smbms_user`
        <!-- 在内容前加上 set 并且忽略内容最后的逗号 且在内容后面加上查询条件  -->
        <trim prefix="set" suffixOverrides="," suffix="where id=#{id}">
            <if test="userCode!=null">`userCode` = #{userCode} , </if>
            <if test="userName!=null">`userName` = #{userName} , </if>
        </trim>

6 foreach循环遍历

此标签的属性如下

  1. item表示集合中每一个元素进行迭代时的别名
  2. index:指定一个名字,用于表示每次迭代的位置.好比for循环中自定义的 i
  3. open表示该语句以什么开始,在in条件语句中以"("开始
  4. separator表示在每次进行迭代之间以什么符号作为分隔 符,在in条件语句中以逗号进行分隔
  5. close表示以什么结束。在in条件语句中以")"结尾

在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,主要有以下3种情况:

  1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
  2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
  3. 如果传入的参数是多个的时候,我们一般把它们封装成一个Map了,此时属性值为map其中的一个key

栗子1

当入参为list时

<select id="getUSerByRoleId_foreach_list" resultMap="userMapByRole">
        select * from smbms_user where userRole in
        <!-- 因为此处用了in,因此以 "("开头  ,")"结尾 ,","分隔 -->
        <foreach collection="list" item="roleList" open="(" separator="," close=")">
            #{roleList}
        </foreach>
    </select>

栗子2

当入参为数组时

<select id="getUserByRoleId_foreach_array" resultMap="userMapByRole">
        select * from smbms_user where userRole in
        <!-- 因为此处用了in,因此以 "("开头  ,")"结尾 ,用","分隔 -->
        <foreach collection="array" item="roleIds" open="(" separator="," close=")">
            #{roleIds}
        </foreach>
    </select>

栗子3

当为map时

<select id="getProvider"  resultMap="providerresult">
        SELECT * FROM smbms_bill b JOIN smbms_provider p  ON b.providerId=p.id
        where b.providerId in
        <!-- 因为此处用了in,因此以 "("开头  ,")"结尾 ,","分隔 此时的collection的值是map其中的一个key-->
        <foreach collection="#{bibli}" item="pros" open="(" separator="," close=")">
            <!-- 获取对象当中的属性 -->
            #{pros.providerId}    
        </foreach>
    </select>

7 小结

  • if+set:动态完成更新操作
  • if+where:动态完成多条件查询
  • if+trim:完成多条件查询(代替where)或者更新操作(代替set)
  • choose(when,otherwise):动态完成多条件查询(多选一)
  • foreach:主要用于in条件查询中,迭代集合,最关键的部分为collection属性,根据不同的入参类型,该属性值则不同
  1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
  2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
  3. 如果传入的参数是多个的时候,我们一般把它们封装成一个Map了,此时属性值为map其中的一个key
目录
相关文章
|
3月前
|
SQL Java 测试技术
3、Mybatis-Plus 自定义sql语句
这篇文章介绍了如何在Mybatis-Plus框架中使用自定义SQL语句进行数据库操作。内容包括文档结构、编写mapper文件、mapper.xml文件的解释说明、在mapper接口中定义方法、在mapper.xml文件中实现接口方法的SQL语句,以及如何在单元测试中测试自定义的SQL语句,并展示了测试结果。
3、Mybatis-Plus 自定义sql语句
|
13天前
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
1月前
|
SQL Java 数据库连接
mybatis使用四:dao接口参数与mapper 接口中SQL的对应和对应方式的总结,MyBatis的parameterType传入参数类型
这篇文章是关于MyBatis中DAO接口参数与Mapper接口中SQL的对应关系,以及如何使用parameterType传入参数类型的详细总结。
30 10
|
2月前
|
SQL XML Java
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
文章介绍了MyBatis中动态SQL的用法,包括if、choose、where、set和trim标签,以及foreach标签的详细使用。通过实际代码示例,展示了如何根据条件动态构建查询、更新和批量插入操作的SQL语句。
mybatis复习03,动态SQL,if,choose,where,set,trim标签及foreach标签的用法
|
3月前
|
SQL Java 数据库连接
Mybatis系列之 Error parsing SQL Mapper Configuration. Could not find resource com/zyz/mybatis/mapper/
文章讲述了在使用Mybatis时遇到的资源文件找不到的问题,并提供了通过修改Maven配置来解决资源文件编译到target目录下的方法。
Mybatis系列之 Error parsing SQL Mapper Configuration. Could not find resource com/zyz/mybatis/mapper/
|
2月前
|
SQL XML Java
mybatis :sqlmapconfig.xml配置 ++++Mapper XML 文件(sql/insert/delete/update/select)(增删改查)用法
当然,这些仅是MyBatis功能的初步介绍。MyBatis还提供了高级特性,如动态SQL、类型处理器、插件等,可以进一步提供对数据库交互的强大支持和灵活性。希望上述内容对您理解MyBatis的基本操作有所帮助。在实际使用中,您可能还需要根据具体的业务要求调整和优化SQL语句和配置。
44 1
|
3月前
|
SQL Java 数据库连接
Mybatis系列之 动态SQL
文章详细介绍了Mybatis中的动态SQL用法,包括`<if>`、`<choose>`、`<when>`、`<otherwise>`、`<trim>`和`<foreach>`等元素的应用,并通过实际代码示例展示了如何根据不同条件动态生成SQL语句。
|
3月前
|
SQL Java 关系型数据库
SpringBoot 系列之 MyBatis输出SQL日志
这篇文章介绍了如何在SpringBoot项目中通过MyBatis配置输出SQL日志,具体方法是在`application.yml`或`application.properties`中设置MyBatis的日志实现为`org.apache.ibatis.logging.stdout.StdOutImpl`来直接在控制台打印SQL日志。
SpringBoot 系列之 MyBatis输出SQL日志
|
3月前
|
SQL 关系型数据库 MySQL
解决:Mybatis-plus向数据库插入数据的时候 报You have an error in your SQL syntax
该博客文章讨论了在使用Mybatis-Plus向数据库插入数据时遇到的一个常见问题:SQL语法错误。作者发现错误是由于数据库字段中使用了MySQL的关键字,导致SQL语句执行失败。解决方法是将这些关键字替换为其他字段名称,以避免语法错误。文章通过截图展示了具体的操作步骤。
|
4月前
|
SQL Java 数据库连接
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
idea中配置mybatis 映射文件模版及 mybatis plus 自定义sql
91 3