Skip to content

8.动态sql

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

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

8.1 If

使用if根据条件动态拼接sql,常用语where条件

xml
<select id="selectListofEntity" resultMap="resultMap" parameterType="com.neuedu.entity.UploadFile">
        select * from upload_files
        where 1=1
        <if test="originName!=null and originName != ''">
            and origin_name = #{originName}
        </if>
    </select>

8.2 where

where元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。

xml
<select id="selectListofEntity" resultMap="resultMap" parameterType="com.neuedu.entity.UploadFile">
        select * from upload_files
        <where >
            <if test="originName!=null and originName != ''">
                and origin_name = #{originName}
            </if>
             <if test="size!=null">
                and size > #{size}
            </if>
        </where>
    </select>

8.2.1 单元测试的情况

java
@Test
public void selectListofEntity() {
    SqlSession session = sqlSessionFactory.openSession();
    UploadFilesMapper uploadFilesMapper = session.getMapper(UploadFilesMapper.class); //通过mybatis产生一个 代理对象


    UploadFile param = new UploadFile();
    //通过控制参数达到动态拼接sql的目的
    param.setOriginName("314.png");
    param.setSize(500L);

    List<UploadFile> list = uploadFilesMapper.selectListofEntity(param);
    for (UploadFile o : list) {
        System.out.println(o);
    }
    session.close();
}

8.2.2 等价的trim标签

xml
<select id="selectListofEntity" resultMap="resultMap" parameterType="com.neuedu.entity.UploadFile">
        select * from upload_files
        <trim prefix="where" prefixOverrides="and|or">

            <if test="originName!=null and originName != ''">
                or origin_name = #{originName}
            </if>
            <if test="size!=null">
                or size > #{size}
            </if>
     </trim>
    </select>

8.3 set标签

set元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)。

xml
<update id="update" parameterType="com.neuedu.entity.UploadFile">
        UPDATE
        upload_files
        <set>
            <if test="originName!=null and originName!='' ">
                origin_name= #{originName},
            </if>
            <if test="path!=null and path!='' ">
                path= #{path},
            </if>
            <if test="uploadTime!=null ">
                upload_time= #{uploadTime},
            </if>
            <if test="size!=null ">
                size= #{size},
            </if>
            <if test="ip!=null and ip != ''">
                ip= #{ip},
            </if>
        </set>
        WHERE id= #{id}

    </update>

8.3.1单元测试

java
@Test
public void update() {
    SqlSession session = sqlSessionFactory.openSession();
    UploadFilesMapper UploadFilesMapper = session.getMapper(UploadFilesMapper.class); //通过mybatis产生一个 代理对象
    Integer id = 24;

    UploadFile uploadFile = UploadFilesMapper.selectById(id);
    System.out.println("update before :  "+uploadFile);

    uploadFile.setOriginName(uploadFile.getOriginName()+"-2021年3月22日16:19:14");
    int count = UploadFilesMapper.update(uploadFile);
    session.commit();


    uploadFile = UploadFilesMapper.selectById(id);
    System.out.println("count = " + count);
    System.out.println("update after :  "+uploadFile);
}

8.3.2 等价的trim标签

xml
<update id="update" parameterType="com.neuedu.entity.UploadFile">
    UPDATE
    upload_files

    <trim prefix="set" suffixOverrides=",">
        <if test="originName!=null and originName!='' ">
            origin_name= #{originName},
        </if>
        <if test="path!=null and path!='' ">
            path= #{path},
        </if>
        <if test="uploadTime!=null ">
            upload_time= #{uploadTime},
        </if>
        <if test="size!=null ">
            size= #{size},
        </if>
        <if test="ip!=null and ip != ''">
            ip= #{ip},
        </if>
    </trim>
    WHERE id= #{id}

</update>

8.4 choose (when ,otherwise)

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。

当第一个when条件成立则第一个条件作为sql的一部分,否则继续后面 when 判断,所有的when 都不满,则拼接otherwise的条件

xml
<select id="selectCount" resultType="int">
        select count(1) from upload_files

        where 1=1
    <choose>
        <when test="originName!=null and originName != ''">
            and origin_name = #{originName}
        </when>
        <otherwise>
            and size > #{size}
        </otherwise>

    </choose>
</select>

8.5 trim

属性名属性解释
prefix要添加的前缀。比如这里因为没有使用WHERE,按照语法格式条件必须要有WHERE。此时就可以使用prefix属性给整个条件语句块前面添加一个WHERE关键字。
prefixOverrides要删除的前缀。如果多出来指定的前缀,则将这些多出来的前缀修剪去除。比如:如果在整个语句中需要修剪去AND
suffix要添加的后缀。使用方式与prefix类似,只是prefix是增加前缀,而suffix是添加一个后缀在被包裹的语句块中。
suffixOverrides要删除的后缀。使用方式与prefixOverrides类似,只是一个是去除前面多余的关键字,suffixOverrides是删除多余后面的。

8.6 foreach

动态 SQL 的另一个常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)

8.6.1 Statement写法

xml
<delete id="deleteBatch">
        DELETE FROM upload_files WHERE id IN

        <foreach item="item" index="index" collection="list"  open="(" separator="," close=")">
            #{item}
        </foreach>

    </delete>

    <delete id="deleteBatch2">
        DELETE FROM upload_files WHERE id IN

        <foreach item="item" index="index" collection="array"  open="(" separator="," close=")">
            #{item}
        </foreach>

    </delete>

8.6.12 Mapper接口

java
 public int deleteBatch( List list);

 public int deleteBatch2(Integer[] ids);

8.7 bind

用于在ongl上下文中定义变量

8.7.1 Statement语句

xml
<select id="selectListofEntityWithBind" resultMap="resultMap" parameterType="com.neuedu.entity.UploadFile">
        select * from upload_files
    <where >

        <if test="originName!=null and originName != ''">
            <bind name="originNameAlias" value="  '%'+originName+'%'  "/>
            and origin_name  like '${originNameAlias}'
        </if>

    </where>
</select>

8.7.2 Mapper声明

java
public List<UploadFile> selectListofEntityWithBind(UploadFile uploadFile)

8.7.3 单元测试

java
@Test
public void selectListofEntityWithBind() {
    SqlSession session = sqlSessionFactory.openSession();
    UploadFilesMapper uploadFilesMapper = session.getMapper(UploadFilesMapper.class); //通过mybatis产生一个 代理对象


    UploadFile param = new UploadFile();
    param.setOriginName("314");

    List<UploadFile> list = uploadFilesMapper.selectListofEntityWithBind(param);
    for (UploadFile o : list) {
        System.out.println(o);
    }
    session.close();
}

Released under the MIT License.